Hi there, I got an idea while writing a library. There are multiple cases where I got this:
template<typename T, std::enable_if_t<std::is_polymorphic<T>::value, int> = 0>
void doThings(T) {
// ...
}
template<typename T, std::enable_if_t<!std::is_polymorphic<T>::value, int> = 0>
void doThings(T) {
static_assert(!std::is_same<T, T>::value, "T must not be polymorphic.");
}
This code gives me clear error messages, nice. But there's a catch: You can't use SFINAE to check if the function is callable:
template<typename T>
auto callDoThingsMaybe(T t) -> decltype(doThings(t)) {
doThings(t);
}
template<typename T>
auto callDoThingsMaybe(T t) -> decltype(doOtherThings(t)) {
doOtherThings(t);
}
Where doOtherThings(T) only exists if T is polymorphic.
This code won't work, because doThings(T) is not a SFINAE failure, and calling it will result in a hard error. If I would remove the overload that throws the static assert, SFINAE will work, but we will loose the nice error message.
I would like to make a proposal to enable sfinae with nice error messages.
Look at this alternative:
template<typename T, std::enable_if_t<!std::is_polymorphic<T>::value, int> = 0>
void doThings(T) = delete("T must not be polymorphic."); // proposed syntax
This will follow deleted function rules and give a nice error message when it is called. SFINAE will still work, and the compiler will still print nice error messages for users.
What do you think?