I came to the following example of using a concept, which checks if the member function is present in the class and then using this concept in the friend function. For example, to overload operator<<
for a bunch of similar classes
#include <iostream>
#include <vector>
template<class T>
concept Sizable = requires(T a)
{
{a.size()} -> std::same_as<size_t>;
};
template<class T> requires Sizable<T>
std::ostream& operator<<(std::ostream& os, const T& a);
template<class T>
class A {
std::vector<T> storage;
public:
size_t size() const { return storage.size();}
friend std::ostream& operator<< <A<T>>(std::ostream& os, const A<T>& a);
};
template<class T> requires Sizable<T>
std::ostream& operator<<(std::ostream& os, const T& a)
{
for (size_t i = 0; i < a.size(); ++i) {
}
return os;
}
int main()
{
A<int> a;
operator<< <A<int>>(std::cout, a);
}
However this code fails to compile for the reason that we have a member access into incomplete type.
Is there any way how this can be achieved, taking into account that we cannot forward declare concepts?
If the friend definition is moved inside a class then the code compiles and works.