Search code examples
c++templatesfriendfunction-templates

Why do I have `-Wunsupported-friend` warning when I compile friend function template?


I want to declare member function of template class as friend. But I got warning message such as warning: dependent nested name specifier 'Schedule<T>::' for friend class declaration is not supported; turning off access control for 'Manager' [-Wunsupported-friend]

My code is like below

template<typename T>
class Task{};

template<typename T>
class Schedule {
    public:
        void dispatch(Task<T>*) {}
};

class Manager {
    template<typename T>
    friend class Task;

    template<typename T>
    friend void Schedule<T>::dispatch(Task<T>*); // <== Warning here!!!!

    template<typename T>
    friend int ticket() {
        return ++Manager::count;
    }

    static int count;

};

What causes this warning and how can I fix it?


Solution

  • This is a warning you get when using a feature that is not fully implemented in LLVM.

    From the LLVM source code:

    /// True if this 'friend' declaration is unsupported.  Eventually we
    /// will support every possible friend declaration, but for now we
    /// silently ignore some and set this flag to authorize all access.
    unsigned UnsupportedFriend : 1;
    

    You can safely ignore the warning if you are not worried about the "all access" granted to all Schedule<T>s member functions. I'm assuming you got the warning when compiling with -Weverything, so just add -Wno-unsupported-friend afterwards - or be pragmatic and make the whole class a friend:

    template<typename T>
    friend class Schedule;
    

    The effect of the authorization of all access to all Schedule<T>s member functions can be illustrated like this:

    class Manager;
    
    template <typename T>
    class Schedule {
    public:
        void dispatch() {}
        void other(Manager&);                // not befriended
    };
    
    class Manager {
    public:
        template <typename T>
        friend void Schedule<T>::dispatch(); // becomes `friend class Schedule<T>;`
    
    private:
        int x = 0;
    };
    
    template <typename T>
    void Schedule<T>::other(Manager& m) {
        ++m.x;                               // should not compile, but does
    }