I produced a code that has implementation divergence and I want to know which compiler is right and why, or which part of the standard allows those compiler to differ:
#include <type_traits>
#include <cstdio>
// Only deleted when the constraint is not met
template<typename T>
struct deleted {
template<typename U = T> requires (not std::is_integral_v<U>)
deleted() = delete;
template<typename U = T> requires std::is_integral_v<U>
deleted() {}
};
struct trigger_error {
template<typename F>
operator F () {
static_assert(not std::is_same_v<F, F>, "Cannot call f with floating point types");
return F{};
}
};
// Constrained function. Only callabale with integral types
// When called with something other than integral, display static assert.
// sfinae still applies even though the static assert is called.
template<typename T> requires std::is_integral_v<T>
void f(T) {}
template<typename T> requires (not std::is_integral_v<T>)
auto f(T, int = trigger_error{}, deleted<T> = {}) {};
// Do sfinae if f is callable. If callable, prints "integrals"
template<typename T> requires(requires(T t){f(t);})
auto use_constrains(T) -> void {
puts("integrals");
}
// Sfinae fails, print "floats" instead
template<typename T>
auto use_constrains(T) -> void {
puts("floats");
}
int main() {
use_constrains(1);
//f(1.3); // uncommenting triggers static assert
use_constrains(1.3);
}
To my surprise, the code don't even compiled on Clang and do an hard error on the call to deleted function deleted::deleted()
.
MSVC compiles, but don't do sfinae, and don't do hard error and simply prints "integrals"
on both calls.
Since the three implementations diverges, I wondered who is right and why. Is sfinae applied on the expression of the default value of a parameter?
f
function and work-around classes (deleted<T>
andtrigger_error
). If the function is really deleted (with non integer types), testing its existance is easy and a bunch ofif constexpr
can do a lot of things... Having said that, I think that those edge cases are not well defined otherwise compiler would probably agree. – Pamella