This works and outputs "1", because the function's constraints are partially ordered and the most constrained overload wins:
template<class T>
struct B {
int f() requires std::same_as<T, int> {
return 0;
}
int f() requires (std::same_as<T, int> && !std::same_as<T, char>) {
return 1;
}
};
int main() {
std::cout << B<int>{}.f();
}
This works as well, because explicit instantiation doesn't instantiate member functions with unsatisfied constraints:
template<class T>
struct B {
int f() requires std::same_as<T, int> {
return 0;
}
int f() requires (!std::same_as<T, int>) {
return 1;
}
};
template struct B<int>;
So what should this do?
template<class T>
struct B {
int f() requires std::same_as<T, int> {
return 0;
}
int f() requires (std::same_as<T, int> && !std::same_as<T, char>) {
return 1;
}
};
template struct B<int>;
Currently this crashes trunk gcc because it compiles two functions with the same mangling. I think it would make sense to compile only the second function, so that the behavior is consistent with the regular overload resolution. Does anything in the standard handle this edge case?