Basically, how can I make the following code compiles?
https://godbolt.org/z/6oM3aGY6d
#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;
}
I’m trying to check if BigStruct exist in a type, and enable f if it does.
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
>Solution :
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) {}