Compiling the following code results in: error: satisfaction of atomic constraint 'requires(T v) {bar(v);} [with T = T]' depends on itself
.
#include<iostream>
#include<vector>
template<class T>
concept Barable = requires(T v)
{
bar(v);
};
struct Foo
{
template<class T> requires Barable<T>
Foo(T) {};
friend void bar(Foo) {
std::cout << "Foo";
};
};
void bar(std::vector<Foo>) {
std::cout << "vector";
}
int main()
{
auto v = std::vector<Foo>{};
bar(v);
}
I understand how checking this concept leads to a circular dependency. What I don’t understand is why, with this setup, the compiler gives an error.
From my understanding, it should just not add bar(Foo)
to the overload set and use bar(std::vector<Foo>)
. For any other type it seems to work that way.
Notes:
- I checked with the trunk versions of both gcc and clang
- marking
Foo(T)
explicit, or providing a constructorFoo(std::vector<Foo>)
solves the problem - changing to some other type (e.g.
int
orstd::vector<int>
) solves the problem - Demo: https://godbolt.org/z/6rT6a4MvP
- I originally stumbled upon this when playing around with Sean Parent’s ‘Inheritance is the base class of all evil’ code
David Ochsner is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.