if constexpr and requires-expression for ad-hoc concepts checking
It works starting from C++2a and gcc 10: https://wandbox.org/permlink/qH34tI6oRJ3Ck7Mm
Here is a working example of using concept
inside if constexpr
for checking if a type has the method foo with a specific return type T provided as a template parameter:
template<class P, class T>
concept Fooable = requires(P p) {
requires std::same_as<decltype(p.foo()), T>;
};
template<typename T>
void printIsFooable(const auto& p) {
if constexpr( Fooable<decltype(p), T> ) {
std::cout << "fooable <" << typeid(T).name() << ">" << std::endl;
}
else {
std::cout << "not fooable <" << typeid(T).name() << ">" << std::endl;
}
}
struct MyFoo {
void foo() const {}
};
int main() {
printIsFooable<void>(MyFoo{}); // fooable <v>
printIsFooable<int>(MyFoo{}); // not fooable <i>
printIsFooable<void>(int{}); // not fooable <v>
}
Code compiles with C++20 in GCC and in Clang.
Concepts issue 3 ("Allow requires-expressions in more contexts") was given WP status in June. And judging by the current looks of [expr.prim.req], in particular p6:
The substitution of template arguments into a requires-expression may result in the formation of invalid types or expressions in its requirements or the violation of the semantic constraints of those requirements. In such cases, the requires-expression evaluates to
false
; it does not cause the program to be ill-formed.
I'd say your code is fine, and GCC hasn't implemented the resolution of issue 3 properly.