0

I'm trying to use std::is_same::value in my application code. Below is just a sample code I've written to recreate my application code. But I get below compiler error:

error: no matching function for call to ‘Y::getName(bool&, bool&)’

Declaration file:

class X {
    std::string getName(bool a = false, bool b = false) { ... } 
};

class Y {
    std::string getName(bool a = false) { ... }
};

template<typename T>
std::string getMyName(const T &obj, bool a = false, bool b = false);

Application file:

template<typename T>
std::string getMyName(const T &obj, bool a, bool b)
{
    if (std::is_same<T, X>::value)
        return obj->getName(a, b);
    else
        return obj->getName(a);
}

void callerFunc()
{
    ...
    ...
    // X and Y are of pointer types 
    std::string strY = getMyName<Y>(y, true);
    std::string strX = getMyName<X>(x, true, true);
}

I'm using C++11 and can't use later versions. Please advise if there is something wrong with my usage.

  • If `x` and `y` are of pointer types then you need `getMyName(*y, true);` and `getMyName(*x, true, true)` – NutCracker May 04 '20 at 09:34
  • 1
    Both branches must be correct regardless of whether `std::is_same::value` is true. (And it is never true if `T` is a pointer type.) – molbdnilo May 04 '20 at 09:41

2 Answers2

0

A function must be possible to be compiled as a whole (even if one branch is never used). The only exception to that rule is if you use C++17 if constexpr - it conditionally disables compilation of part of a function.

However, you can use simple overloading.

std::string getMyName(const X &obj, bool a, bool b)
{
        return obj->getName(a, b);
}

template<typename T>
std::string getMyName(const T &obj, bool a)
{
        return obj->getName(a);
}

Then you need to let your compiler deduce the template type instead of providing it (otherwise compiler won't be able to choose non-template overload). If function template arguments are used as function arguments, you don't need to provide that type explicitly in <>. You can add it back for the function that should use template, but you mustn't add it for function that should use X class.

void callerFunc()
{
    ...
    ...
    // X and Y are of pointer types 
    std::string strY = getMyName(y, true);
    std::string strX = getMyName(x, true, true);
}

See it online (with some changes to make it compile)

Yksisarvinen
  • 18,008
  • 2
  • 24
  • 52
  • This answer uses "if" : https://stackoverflow.com/questions/13636540/how-to-check-for-the-type-of-a-template-parameter – Ashish Malhotra May 04 '20 at 09:51
  • std::string strY = getMyName(y, true); Here I took an example of Y but there are many like Y1, Y2, Y3 so I will have to call the function by providing the type. – Ashish Malhotra May 04 '20 at 09:52
  • @AshishMalhotra Yes, but the function has to correct. `if` doesn't change anything. Without `if constexpr` you need to ensure that both branches are correct and can be compiled. – Yksisarvinen May 04 '20 at 09:55
  • @AshishMalhotra But compiler can deduce template type from argument. It doesn't matter how many `Y` are there, `getMyName(yObjectName, true);` will work (provided that all of these classes provide `getName` method) – Yksisarvinen May 04 '20 at 09:57
0

May be a better design is to overload that getter function for a different number of arguments, so that you can call it directly without having to use std::is_same at all:

struct X {
    std::string getName(bool a, bool b);
    std::string getName(bool a) { return getName(a, false); }
    std::string getName() { return getName(false, false); }
};

struct Y {
    std::string getName(bool a);
    std::string getName() { return getName(false); }
};

Or have different getter functions for different behaviours with 0 arguments.

Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271