简体   繁体   中英

c++ friend function of template with two parameters

Let I have such class Foo and its friend function ::f :

template <typename T>
class Foo {
public:
    template <typename U>
    friend inline void f(Foo<T>, Foo<U>) {}     
};

Then I call it like this f(Foo<double>(), Foo<int>()) , friend of who will be ::f ?

Only Foo<double> or it will be friend of Foo<int> also, I mean ::f become friend for Foo<T> for any T at the time of declaration, or at the time of usage compiler generate ::f for T=double and find out that it is friend of Foo<double> and not friend of Foo<int> ?

And if I declare ::f like this:

template <typename T>
class Foo {
public:
    template <typename U1, typename U2>
    friend inline void f(Foo<U1>, Foo<U2>) {}
};

Again friend of who become ::f after call f(Foo<double>(), Foo<int>());

Note : the second variant compiled only by clang, not gcc.

Note it would be great to see answers with reference to standard.

You don't have a single function template - you have an unbounded family of them. With each instantiation Foo<X> , a new function template is defined,

template <typename U>
void f(Foo<X>, Foo<U>) {}

All instantiations of this template are friends of Foo<X> (but not of any Foo<U> for U != X ).

Thus, when you write f(Foo<double>(), Foo<int>()) , Foo<double> and Foo<int> are instantiated, and with them, two overloads of f are defined:

template <typename U>
void f(Foo<double>, Foo<U>) {}

template <typename U>
void f(Foo<int>, Foo<U>) {}

Overload resolution selects the first one for the call (the second is not viable), which is instantiated for U==int . This instantiation, f<int>(Foo<double>, Foo<int>) , is a friend of Foo<double> but not Foo<int> .


In your second example, I believe gcc is right in rejecting the code, and clang is wrong in accepting it (for what it's worth, MSVC agrees with gcc). Every instantiation of Foo<X> introduces a definition of the same template into the enclosing scope:

template <typename U1, typename U2>
void f(Foo<U1>, Foo<U2>) {}

When a translation unit performs two instantiaions of Foo , it ends up with two identical definitions of f , hence the error.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM