在模板函数

时间:2017-08-15 21:08:36

标签: c++ c++11 templates template-specialization

我正在开发一个具有模板功能的项目:

template <class T> 
T foo<T>(T val) { return someFunc(val); }

template <>
bool foo<bool>(bool val) { return otherFunc(val); };

现在,我有一个班级Bar,我不想接受它作为输入。实际上,我希望它能够生成一个容易发现的编译错误。问题是,如果我这样做:

template <>
Bar foo<Bar>(Bar val) { static_assert(false,"uh oh..."); }

每次编译都失败了。我找到了https://stackoverflow.com/a/3926854/7673414,它说我需要引用模板类型,否则静态断言总会发生。问题是我这里没有模板类型。如果我这样做:

template< typename T >
struct always_false { 
    enum { value = false };  
};

template <>
Bar foo<Bar>(Bar val) { static_assert(always_false<Bar>::value,"uh oh..."); }

然后它也总是无法编译。有没有办法确保类型为Bar的模板的实例化总是导致编译错误?

4 个答案:

答案 0 :(得分:20)

由于foo是一个完整的特化,它总是被编译,静态断言总是被调用。

但是,有一个easier way

template <>
Bar foo<Bar>(Bar val) = delete;

这将说明此特定版本已删除,无法调用。

答案 1 :(得分:3)

另一种方法是仅在类型与Bar

不同时启用模板(非专用版本)
template <class T> 
typename std::enable_if< ! std::is_same<T, Bar>::value, T>::type foo<T>(T val)
 { return someFunc(val); }

如果您可以使用C ++ 14,可以使用std::enable_if_t

进行简化
template <class T> 
std::enable_if_t< ! std::is_same<T, Bar>::value, T> foo<T>(T val)
 { return someFunc(val); }

答案 2 :(得分:2)

您可以使用std::is_same来帮助满足您的要求。

template <class T> 
T foo<T>(T val)
{
   // Make sure T is not Bar
   static_assert(std::is_same<T, Bar>::value == false, "uh oh...");
   return someFunc(val);
}

答案 3 :(得分:1)

如果您使用的是c ++ 17,则可以将所有内容与template< typename T > auto foo( T val ) { static_assert( !std::is_same_v<T,Bar> ); if constexpr( std::is_same_v<T,bool> ) { return other_func( val ); } else { return some_func( val ); } }

放在一起
static_assert

然后你可以在第一行{{1}},没有模板特定实例化的编译失败的痛苦。

enter image description here

提供了一个实时示例