Home > database >  How to use some type specific function (such as .size() for std::string or std::vector and so on) on
How to use some type specific function (such as .size() for std::string or std::vector and so on) on

Time:03-15

If possible, how could I use some type-specific function (such as .size() for: std::string or std::vector or ...) in a function with a template type, being sure that when I'll use that type-specific function I'm actually calling it with the correct type as argument? Maybe I'm wrong, and if it is, please explain to me what I have to do.

#include <iostream>
#include <string>

template <typename T>
std::string func(T& number) {
    if (typeid(T) == typeid(std::string)) {
        unsigned short int size = number.size();// !
        return " is a string";
    }
    else if (typeid(T) == typeid(int)) {
        return " is an int";
    }
    //...
}

int main() {
    std::string name = "Anthony";
    int age = 8;
    std::cout << name /*<< func(name) */<< '\n' << age << func(age) << '.';
    return 0;
}

I know that in the code above the line:

unsigned short int size = number.size();//(I need exactly '.size()')

doesn't make any sense (even the whole code doesn't make much sense) considering that I never use that value, but to find the size of the string (when it is a string!) is exactly what I need, and to not post a very long code that would make sense, I'm posting only this to make it give the error I've had when trying to compile, and in order to give you a minimal reproducible example. So please, don't say to me "just delete that line and your code will work").

CodePudding user response:

Instead of if (typeid(T) == typeid(std::string)), use if constexpr (std::is_same_v<T, std::string>). ( Similarly, else if constexpr instead of else if).

Regular if requires both branches to be valid, even if the condition is known at compile-time. if constexpr requires a compile-time condition, but allows the discarded branch to be invalid (only if the error is related to the template argument; every branch has to be theoretically valid for some template argument).

std::is_same_v<T, std::string> is similar to typeid(T) == typeid(std::string), except it counts as a compile-time constant. if constexpr would reject the latter.

CodePudding user response:

If you really need to use a template here, simply specialize the template.

template <typename T>
std::string func(T& number);

template<>
std::string func<std::string>(std::string& number) {
    unsigned short int size = number.size();// !
    return " is a string";
}

template<>
std::string func<int>(int& number) {
    return " is an int";;
}

Usually you using a template you want to avoid using specific implementations for types though. Overloads would be preferrable for a limited set of types using type-specific implementations though.

CodePudding user response:

Since your requirement is not restricted to std::string(as you have mentioned std::vector etc), you can use SFINAE as shown below:


#include <iostream>
#include<typeinfo>
#include<string>
#include<vector>
#include <type_traits>
//make sure that this overload is added to the set when T has a size() member function which is your requirement
template<typename T> 
auto func(T const& number) -> decltype((void)(number.size()), std::string())
{
    auto size = number.size();
    return " is a "   std::string(typeid(number).name());
    
}
template<typename T>
std::enable_if_t<std::is_fundamental_v<std::remove_reference_t<T>>,std::string> func(T const& number)
{
    return " is a "   std::string(typeid(number).name());
}
int main()
{
    
    std::string name = "Anthony";
    int age = 8;
    double dage = 22.2;
    std::cout << name << func(name) << '\n' << age << func(age) << '.'<<"\n"<<dage << func(dage);
    
    //lets test it with vector 
    std::vector<int> vec= {1,2,3};
    std::cout<<"\nvec: "<< func(vec);
    
    return 0;
}

Demo

The output of the above program can be seen here:

Anthony is a NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
8 is a i.
22.2 is a d
vec:  is a St6vectorIiSaIiEE
  • Related