Compare templated type to certain class/type in C++

Viewed 62

I am trying to find the type of thee class passed into a template as such

template<typename ret> 
ret copy(ret var){
    if(ret == int){ //problematic line
       cout << "int" << endl;
    }
    return var;
}

int main()
{
    int a = 5;
    auto b = copy(a);
    cout << b << endl;

    return 0;
}

But it is returning an error:

main.cpp: In function ‘ret copy(ret)’:
main.cpp:15:12: error: expected primary-expression before ‘==’ token
     if(ret == int){
            ^~
main.cpp:15:15: error: expected primary-expression before ‘int’
     if(ret == int){
               ^~~
main.cpp:15:15: error: expected ‘)’ before ‘int’

How can I do this properly? Thanks

2 Answers

Unlike python, in C++ int is not an object of type class (or something along those lines). You can't compare it like that. Instead, you can use

template<typename ret> 
ret copy(ret var)
{
    if constexpr(std::is_same_v<ret, int>)
    {
        std::cout << "int\n";
    }
    // and so on....

Edit: (in response to comments by yaodav)

Note that if constexpr is supported only by C++17. There are alternatives such as:

    if (std::is_same<ret, int>::value)
    {
        std::cout << "int\n";
    }

but the disadvantage is that if one needs to do anything more complex to var, such as var * 2, then they'd get a syntax error for ret of type std::vector<int>. The if constexpr syntax is not susceptible to this kind of errors, since it does not try to compile the code when if constexpr is false (it only does basic parsing it needs for finding the last }.

If one needs an older C++ version, then the only viable option is overloading:

void copy_helper(int var) {
    std::cout << "int\n";
}
template <class T>
void copy_helper(const T&) {}

template<typename ret> 
ret copy(ret var)
{
   copy_helper(var);

Also note (another comment by yaodav), that using such if construct is a sign of bad design. In general, I prefer to condition things based on properties and capabilities, rather than on specific types (and my overloading example from above is a condition too narrow). For example, if I need an integral type (with +,-,*,/, etc.), then I prefer to condition the code based on the existence of these capabilities.

As stated in the comments, explicit type checking like this is generally a bad design. You can read about template meta-programming, specialization for a better solution to your problem.

If you can use run-time type information, here is a possible solution:

#include <iostream>
#include <typeinfo>

template<typename ret>
ret copy(ret var){
    if(typeid(var) == typeid(int)){
       std::cout << "int" << std::endl;
    }
    return var;
}

int main()
{
    int a = 5;
    auto b = copy(a);
    std::cout << b << std::endl;

    double c = 2.0;
    auto d = copy(c);
    std::cout << d << std::endl;

    return 0;
}
Related