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

69 views Asked by At

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?

1

There are 1 answers

0
Ted Lyngmo On BEST ANSWER

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
}