Here is a struct with a templated constructor that is defined out of line:
template <typename T>
struct Foo {
template <typename F>
Foo(F f);
};
template <typename T>
template <typename F>
Foo<T>::Foo(F f) {}
Clang is happy with this under -std=c++20
. If I add a requires
clause to the templated constructor, it is still happy. But if the requires
clause mentions the struct, it is not happy:
#include <concepts>
template <typename T>
struct Foo {
template <typename F>
requires (!std::same_as<Foo<T>, int>)
Foo(F f);
};
template <typename T>
template <typename F>
requires (!std::same_as<Foo<T>, int>)
Foo<T>::Foo(F f) {}
<source>:13:9: error: out-of-line definition of 'Foo<T>' does not match any declaration in 'Foo<T>'
Foo<T>::Foo(F f) {}
^~~
GCC does accept this.
Is clang right to reject it? And if so, what part of the standard says so?
If you're interested why I have a requires
clause that references the type being constructed, it's to disambiguate the constructor from the move constructor so that the next requires
clause in a larger requires
expression won't be evaluated when F
is the same as Foo
. Otherwise it recursively depends upon itself. The real code is more complicated, and accepts a forwarding reference to F
.