Прежде всего, ограничение шаблона должно быть одинаковым в объявлении и определении (см. [temp.over.link] / 6 ). В противном случае компилятор не сможет определить, к какому объявлению относится определение.
Итак, этот код скомпилируется:
template <typename T>
struct Foo{
Foo(T elem): elem_(elem) {}
template <typename U = T> requires Integral<U>
int get() ;
template <typename U = T> requires Bool<U>
int get() ;
T elem_;
};
template<class T>
template<class U> requires Integral<U>
int Foo<T>::get() {
return -1;
}
template<class T>
template<class U> requires Bool<U>
int Foo<T>::get() {
return 0;
}
Тогда трюк с задержкой проверки концепции, использующий аргумент шаблона по умолчанию, не требуется, поскольку можно связать ограничение с функцией в ее завершающем требовании :
template <typename T>
struct Foo{
Foo(T elem): elem_(elem) {}
int get() requires Integral<T>;
int get() requires Bool<T>;
T elem_;
};
template<class T>
int Foo<T>::get() requires Integral<T> {
return -1;
}
template<class T>
int Foo<T>::get() requires Bool<T> {
return 0;
}