Consider a function template f<T>
with the primary template deleted but some specializations defined. We can use a requires-expression to test if f<T>
has been specialized:
template <typename T>
int f() = delete;
template <>
int f<int>() {
return 1;
}
template <typename T>
int g() {
if constexpr (requires { f<T>; }) {
return f<T>();
} else {
return -1;
}
}
int main() { return g<void>(); }
Version 1 (godbolt link), same as above: compiles on clang but not gcc or msvc.
Version 2 (godbolt link): replacing requires { f<T>; }
with requires { f<T>(); }
it now compiles on gcc as well.
Version 3 (godbolt link): replacing the inline requires-expression with a named concept, it now compiles on all three compilers.
I am curious which of these versions are well-formed C++20 code and which instances represent compiler bugs.