Home > Back-end >  Order of definition of constrainsts and concepts c 20
Order of definition of constrainsts and concepts c 20

Time:12-26

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;
}
  • Related