Where is the right position of a concept or constraint?
The following code compile:
void f(int x) { }
template <typename T>
concept Concept =
requires (T a)
{ f(a); };
template <typename T>
requires Concept<T>
struct A
{ };
int main(){
A<int> a;
}
but if I change the position of the function f(int)
to:
template <typename T>
concept Concept =
requires (T a)
{ f(a); };
void f(int x) { } // <-- new position
template <typename T>
requires Concept<T>
struct A
{ };
int main(){
A<int> a;
}
this doesn't compile in gcc 11.3.0. I get the following error:
main.cpp:27:10: error: template constraint failure for ‘template<class T> requires Concept<T> struct A’
27 | A<int> a;
| ^
main.cpp:27:10: note: constraints not satisfied
main.cpp: In substitution of ‘template<class T> requires Concept<T> struct A [with T = int]’:
main.cpp:27:10: required from here
main.cpp:12:9: required for the satisfaction of ‘Concept<T>’ [with T = int]
main.cpp:13:5: in requirements with ‘T a’ [with T = int]
main.cpp:14:8: note: the required expression ‘f(a)’ is invalid
14 | { f(a); };
CodePudding user response:
If a function is declared after a template, the only way the template can call it is via ADL. int
is a built-in type, so ADL doesn't happen for it.
If the parameter was e.g. a class type, defined in the same namespace as f()
, it would work.
Clang explains this:
...
<source>:5:7: note: because 'f(a)' would be invalid: call to function 'f' that is neither visible in the template definition nor found by argument-dependent lookup
CodePudding user response:
It works if you predeclare the function. It is not defined at that point in the file.
It's the same principle as when calling functions, you need a predeclaration to be able to use it without seeing the definition.
void f(int x);
template <typename T>
concept Concept =
requires (T a)
{ f(a); };
void f(int x) { } // <-- new position
template <typename T>
requires Concept<T>
struct A
{ };
int main(){
A<int> a;
}