How can I make the following code compile?
I'm trying to check if BigStruct exist in a type, and enable f
if it does.
#include <type_traits>
struct A {
using BigStruct = int;
};
struct C {
};
template <typename T>
struct B {
void f(typename T::BigStruct t) requires requires {T::BigStruct;} {}
};
int main() {
B<A> b1;
B<C> b2;
}
Error I got:
<source>:11:24: error: no type named 'BigStruct' in 'C'
void f(typename T::BigStruct t) requires requires {T::BigStruct;} {}
~~~~~~~~~~~~^~~~~~~~~
<source>:16:8: note: in instantiation of template class 'B<C>' requested here
B<C> b2;
^
1 error generated.
ASM generation compiler returned: 1
<source>:11:24: error: no type named 'BigStruct' in 'C'
void f(typename T::BigStruct t) requires requires {T::BigStruct;} {}
~~~~~~~~~~~~^~~~~~~~~
<source>:16:8: note: in instantiation of template class 'B<C>' requested here
B<C> b2;
^
1 error generated.
Execution build compiler returned: 1
Here's a godbolt link for x86-64 clang trunk.
CodePudding user response:
Concept checking for non-template functions happens after the function's signature has been generated. That means the parameter list has to exist. And therefore, it must be syntactically valid.
There's not much you can do in this circumstance, if you don't want to restrict the entire class, besides the old pre-C 20 strategy of making the function itself a template:
template<typename U = T>
requires requires {typename U::BigStruct;}
void f(typename U::BigStruct t) {}