Давайте рассмотрим этот код:
template<class T>
concept Range = requires(T& v){
{begin(v)};
{end(v)};
};
namespace defaults{
template<class T>
auto begin(T& v) -> decltype(v.begin());
template<class T>
auto end(T& v) -> decltype(v.end());
}
//naive "customization points"!
auto begin(Range auto& v){
defaults::begin(v);
}
auto end(Range auto& v){
defaults::end(v);
}
struct my_range{
int * begin();
int * end();
} rng;
auto it = begin(rng); //BOOM
Внутри определения понятия Range
шаблонная функция begin(Range auto& v)
найдена ADL для аргумента типа my_range
.Таким образом, begin(v)
правильная форма зависит от Range<my_range>
, а Range<my_range>
зависит от begin(v)
правильная форма.
Что должно сообщать компилятору в этом случае?
gcc 8.2 (концепция TS) аварийно завершает работу, и ветвь clang, которая реализует концепции, сообщает о превышении глубины рекурсивного создания шаблона.