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?
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.
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); }
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);
}
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