问题
I'm working on a project which has an template function as so:
template <class T>
T foo<T>(T val) { return someFunc(val); }
template <>
bool foo<bool>(bool val) { return otherFunc(val); };
Now, I have a class Bar
, which I don't want to accept as input. In fact, I want it to generate an easy to spot compile error. The problem is that if I do this:
template <>
Bar foo<Bar>(Bar val) { static_assert(false,"uh oh..."); }
It fails on every compile. I found https://stackoverflow.com/a/3926854/7673414, which says that I need to make reference to the template type, otherwise the static assert always takes place. The problem is I don't have a template type here. If I do:
template< typename T >
struct always_false {
enum { value = false };
};
template <>
Bar foo<Bar>(Bar val) { static_assert(always_false<Bar>::value,"uh oh..."); }
then it also always fails compiling. Is there a way to ensure that an instantiation of the template with type Bar
always causes a compile error?
回答1:
Since foo
is a complete specialization, it will always get compiled, and the static assert will always get called.
However, there’s an easier way:
template <>
Bar foo<Bar>(Bar val) = delete;
This will say that this specific version is deleted, and cannot be called.
回答2:
Another way is enable the template (not specialized version) only if the type is different from Bar
template <class T>
typename std::enable_if< ! std::is_same<T, Bar>::value, T>::type foo<T>(T val)
{ return someFunc(val); }
If you can use C++14, is can be simplified using 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); }
回答3:
You can use std::is_same to help with your requirement.
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);
}
回答4:
If you are using c++17, you can put everything together with 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 );
}
}
Then you can static_assert
at the first line, without the pain of compilation failure of the template specific instantiation.
A live example is available at https://wandbox.org/permlink/PpR6G0gcvMRoxhhZ
来源:https://stackoverflow.com/questions/45701567/make-c-fail-compilation-on-specific-instantiation-of-template-function