2

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

Serket
  • 3,785
  • 3
  • 14
  • 45
  • explicitly checking for type this way is usually a symptom of a bad design. Look into template specialization or in your case you could overload the function. – bolov Jul 12 '20 at 18:05

2 Answers2

4

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.

Michael Veksler
  • 8,217
  • 1
  • 20
  • 33
  • but notice that `if constexpr` is from c++17 and `std::is_same` from 11 – yaodav Jul 12 '20 at 18:25
  • @yaodav good point, but without `if constexpr` the meaning or the syntax diverges too much, and overloaing becomes the only reasonable option (if the OP intends to do anything smarter than just printing a predefined string) – Michael Veksler Jul 12 '20 at 18:31
  • if he is a student usually thy learn 98, then the `typeid` is his only option (or template specialization) as you can see in my answer [here](https://stackoverflow.com/questions/60845848/c-returning-reference-to-an-item-in-vector-from-class/60846431#60846431) he has 3 whys to do it depend on the standart that he working with – yaodav Jul 12 '20 at 18:43
2

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;
}
Mukul Gupta
  • 2,310
  • 3
  • 24
  • 39