使 C++ 在模板函数的特定实例化时编译失败
Make C++ fail compilation on specific instantiation of template function
我正在开发一个具有模板功能的项目:
template <class T>
T foo<T>(T val) { return someFunc(val); }
template <>
bool foo<bool>(bool val) { return otherFunc(val); };
现在,我有一个 class Bar
,我不想接受它作为输入。事实上,我希望它生成一个易于发现的编译错误。问题是如果我这样做:
template <>
Bar foo<Bar>(Bar val) { static_assert(false,"uh oh..."); }
每次编译都失败。我发现 ,它说我需要引用模板类型,否则总是会发生静态断言。问题是我这里没有模板类型。如果我这样做:
template< typename T >
struct always_false {
enum { value = false };
};
template <>
Bar foo<Bar>(Bar val) { static_assert(always_false<Bar>::value,"uh oh..."); }
然后它也总是编译失败。有没有办法确保 Bar
类型的模板实例化总是导致编译错误?
您可以使用 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);
}
由于 foo
是一个完整的专业化,它总是会被编译,并且静态断言总是会被调用。
然而,有一个 easier way:
template <>
Bar foo<Bar>(Bar val) = delete;
这里会说这个特定的版本被删除了,无法调用
另一种方法是仅当类型不同于 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); }
如果你使用的是c++17,你可以把所有东西放在一起 constexpr if
:
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
,没有模板特定实例化编译失败的痛苦。
提供了一个实例
我正在开发一个具有模板功能的项目:
template <class T>
T foo<T>(T val) { return someFunc(val); }
template <>
bool foo<bool>(bool val) { return otherFunc(val); };
现在,我有一个 class Bar
,我不想接受它作为输入。事实上,我希望它生成一个易于发现的编译错误。问题是如果我这样做:
template <>
Bar foo<Bar>(Bar val) { static_assert(false,"uh oh..."); }
每次编译都失败。我发现 ,它说我需要引用模板类型,否则总是会发生静态断言。问题是我这里没有模板类型。如果我这样做:
template< typename T >
struct always_false {
enum { value = false };
};
template <>
Bar foo<Bar>(Bar val) { static_assert(always_false<Bar>::value,"uh oh..."); }
然后它也总是编译失败。有没有办法确保 Bar
类型的模板实例化总是导致编译错误?
您可以使用 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);
}
由于 foo
是一个完整的专业化,它总是会被编译,并且静态断言总是会被调用。
然而,有一个 easier way:
template <>
Bar foo<Bar>(Bar val) = delete;
这里会说这个特定的版本被删除了,无法调用
另一种方法是仅当类型不同于 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); }
如果你使用的是c++17,你可以把所有东西放在一起 constexpr if
:
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
,没有模板特定实例化编译失败的痛苦。