Как размещение определения понятия меняет поведение программы

Я компилирую этот код с gcc 9.3 с -fconcepts.

Следующее успешно компилируется

void f(int) {}             // 1

template<typename T>       // 2 
concept C = requires (T a) 
{ { f(a) }; };

template<C T>              // 3
void g() { f(42); }

int main() { g<int>(); }   // 4

Однако, если я определяю функцию f после определения понятия C,

template<typename T>       // 2 
concept C = requires (T a) 
{ { f(a) }; };

void f(int) {}             // 1

template<C T>              // 3
void g() { f(42); }

int main() { g<int>(); }   // 4

то программа не компилируется с

error:
line 4: cannot call function g
because
line 3: constraint not satisfied
because
line 2: required expression f(a) would be ill-formed

Это кажется странным, поскольку к моменту создания экземпляра g<int> уже должно быть видно определение f. Может ли кто-нибудь объяснить, что здесь происходит?

Обратите внимание: если я объявлю f перед определением концепции, то даже если я объявлю f после, программа успешно скомпилируется.


person cigien    schedule 03.04.2020    source источник


Ответы (1)


ADL не относится к int, поэтому f(a)int a) болен формируется, когда не было объявлено ранее.

У вас будет аналогичная проблема с:

void f(int){}

template<typename T>
void g(T t)
{
    f(t);
}
void f(char){}

void h() { g('*'); } // Call f(int)
person Jarod42    schedule 03.04.2020
comment
Итак, насколько я понимаю, о чем вы говорите, в теле g ADL будет рассматривать только те функции, которые были объявлены до него? - person cigien; 03.04.2020
comment
ADL не применяется к фундаментальным типам. Это применимо примерно для классов классов/шаблонов, добавляющих свое пространство имен для поиска. - person Jarod42; 03.04.2020