3

I have a template for some type, and some code in the template are not valid for all types, so I want to skip them when needed.

struct T1
{
    int getData(){return 1;}
};

struct T2
{
    string getData(){return "string";}
};

struct T3
{
    // no getData()
};

template<typename T>
void printData(T param)
{
    cout << param.getData() << endl;
}

int main() {

    T1 t1;
    T2 t2;
    T3 t3;

    printData(t1);
    printData(t2);
    printData(t3);  // fails for T3 has no getData
}

I want to know is there some way like this(pseudo code):

template<typename T>
void printData(T param)
{
    if(T != T3) // compile time check, instance on this condition
    {
        cout << param.getData() << endl;
    }
}

I have tried std::is_same but it did not work

max66
  • 65,235
  • 10
  • 71
  • 111
maidamai
  • 712
  • 9
  • 26

2 Answers2

5

Starting from C++17, you can use if constexpr (!std::is_same_v<T, T3>), as suggested in songyuanyao's answer.

In C++11/C++14 I propose two ways.

(1) tag dispatching

template <typename T>
void printData (T param, std::true_type)
 { }

template <typename T>
void printData (T param, std::false_type)
 { std::cout << param.getData() << std::endl; }

template <typename T>
void printData (T param)
 { printData(param, std::is_same<T, T3>{}); }

(2) SFINAE

// ever enabled
template <typename T>
void printData (T param, long)
 { }

// preferred (int instead of long) but enabled only
// when param support getData()
template <typename T>
auto printData (T param, int)
   -> decltype( param.getData(), void() )
 { std::cout << param.getData() << std::endl; }

template <typename T>
void printData (T param)
 { printData(param, 0); }
max66
  • 65,235
  • 10
  • 71
  • 111
2

The problem is that the statement_true will still be evaluated in compilation when T is T3, which leads to compilation error.

You could use Constexpr If (since C++17).

If the value is true, then statement-false is discarded (if present), otherwise, statement-true is discarded.

e.g.

if constexpr (!std::is_same_v<T, T3>)
{
    cout << param.getData() << endl;
}
songyuanyao
  • 169,198
  • 16
  • 310
  • 405