Search code examples
c++templatesoverloading

Overload template operator of template class that uses SFINAE


I have a template class (with SFINAE condition) and I'd like to overload a template operator << for it.

This code works, but it also allow all operator << overloaded for all types T to access Foo as friends.

How can I get only operator << of type Foo to be friend of Foo class?

I tried forward declaration of Foo class and operator but can make it work because of the use of enable_if

Does anyone have an idea of how to do this?

template< typename T, enable_if_t< condition_v<T>, int> = 0 >
class Foo
{
    // ...

    template< typename Ar, typename R> friend Ar& operator<<(Ar& os, const Foo<R>& foo);          
};

template< typename Ar, typename T>
inline Ar& operator<<(Ar& ar, const Foo<T>& foo)
{
   // ...
   return ar;
}            

Solution

  • The easiest way to resolve friend and template issues is to define the friend within the class(1), usually:

    template< typename T, std::enable_if_t< condition_v<T>, int> = 0 >
    class Foo
    {
        template< typename Ar > friend Ar& operator<<(Ar& os, const Foo& foo) {
            // ...
            return os;
        }          
    };
    

    Note that this defines a function template where Foo is not a template parameter. Only Ar is a template parameter. This is typically desirable because it simplifies overload resolution, which can fix some ambiguous cases, and it may improve compilation speed.


    (1) Colloquially, such a friend is called "hidden friend".