我有某种类型的模板,并且模板中的某些代码并非对所有类型都有效,因此我想在需要时跳过它们。
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
}
我想知道是否有这种方法(伪代码):
template<typename T>
void printData(T param)
{
if(T != T3) // compile time check, instance on this condition
{
cout << param.getData() << endl;
}
}
我尝试了std::is_same
,但没有成功
答案 0 :(得分:5)
从C ++ 17开始,您可以使用if constexpr (!std::is_same_v<T, T3>)
,如Songyuanyao的答案中所述。
在C ++ 11 / C ++ 14中,我提出了两种方法。
(1)标签分发
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); }
答案 1 :(得分:2)
问题在于,当T
为T3
时,仍然会在编译时评估statement_true,这会导致编译错误。
您可以使用Constexpr If(自C ++ 17起)。
如果值为
true
,则丢弃statement-false(如果存在),否则,丢弃statement-true。
例如
if constexpr (!std::is_same_v<T, T3>)
{
cout << param.getData() << endl;
}