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 <bool, typename T>
struct enable_if;
// Specialization for true (also OK)
template <typename T>
struct enable_if<true, T> {
using type = T;
};
// Specialization for false (Wrong!)
template <typename T>
struct enable_if<false, T> {
static_assert(std::is_same<T, T*>::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 T>
typename enable_if<std::is_integral<T>::value, int>::type
test(const T &t);
void test(...);
int main()
{
std::cout << std::is_same<decltype(test(0)), int>::value << std::endl; // OK
std::cout << std::is_same<decltype(test(0.0)), void>::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