Consider this:
template
struct hash
{
static_assert(false,\"Not implemented.\");
};
struct unhashable {};
template
The compilation has to fail in any compliant compiler.
SFINAE rules are based on declarations and not definitions. (Sorry if I'm using the wrong terminology here.) What I mean is the following:
For a class/struct:
template < /* substitution failures here are not errors */ >
struct my_struct {
// Substitution failures here are errors.
};
For a function:
template * substitution failures here are not errors */>
/* substitution failures here are not errors */
my_function( /* substitution failures here are not errors */) {
/* substitution failures here are errors */
}
In addition, the non existence of the struct/function for the given set of template arguments is also subject to SFINAE rules.
Now a static_assert
can only appear in the regions where substitution failures are errors and, therefore, if it fires, you'll get a compiler error.
For instance the following would be a wrong implementation of enable_if
:
// Primary template (OK)
template
struct enable_if;
// Specialization for true (also OK)
template
struct enable_if {
using type = T;
};
// Specialization for false (Wrong!)
template
struct enable_if {
static_assert(std::is_same::value, "No SFINAE here");
// The condition is always false.
// Notice also that the condition depends on T but it doesn't make any difference.
};
Then try this
template
typename enable_if::value, int>::type
test(const T &t);
void test(...);
int main()
{
std::cout << std::is_same::value << std::endl; // OK
std::cout << std::is_same::value << std::endl; // Error: No SFINAE Here
}
If you remove the specialization of enable_if
for false
then the code compiles and outputs
1
1