Let's say I start with this simple example of the use of a C++20 "concept":
template <typename T>
concept HasFoo = requires( T t )
{
t.foo();
};
template <HasFoo T>
void DoFoo( T& thing )
{
thing.foo();
}
class FooThing
{
public:
void foo() {}
};
int main(int argc, const char * argv[]) {
FooThing x;
DoFoo( x );
return 0;
}
This compiles, and the concept verifies that the FooThing class has a method foo. But suppose I want to make the method foo private, and call DoFoo on the FooThing from
another method of FooThing. So I try adding a friend declaration:
class FooThing
{
private:
void foo() {}
friend void DoFoo<FooThing>( FooThing& thing );
};
This results in an error message: FooThing does not satisfy HasFoo because t.foo() would be invalid: member access into incomplete type FooThing.
To reassure myself that the concept really is essential to this problem, I tried doing without it,
template <typename T>
void DoFoo( T& thing )
{
thing.foo();
}
and then the error goes away. Is there any way to fix the error while keeping the concept?
If I try the suggestion of an attempted answer and add a forward declaration
template<typename T> void DoFoo(T&);
before the class, then the compile error goes away, but I get a link error saying that DoFoo(FooThing&) or DoFoo<FooThing>(FooThing&) is an undefined symbol.