How to define a friend template function of a template class outside of its declaration?

丶灬走出姿态 提交于 2019-12-08 03:13:26

问题


If I define the friend template function inside the template class declaration, as follows, it can compile.

#include <iostream>

template <typename T>
class X {
public:
    X(int i) : n(i) {}

private:
    T n;

    template <typename U> 
    friend void doStuff(const X<T>& x, const U& u)
    {
        std::cout << (x.n + u) << std::endl;
    }
};

int main()
{
    X<int> x(1);
    doStuff(x, 3);
    return 0;
}

But if I move the definition of doStuff() out of the class decalaration, just after the declaration of class X<>, as follows, it can't compile.

template <typename U>
template <typename T>
void doStuff(const X<T>& x, const U& u)
{
    std::cout << (x.n + u) << std::endl;
}

Neither does the following code.

template <typename U, typename T>
void doStuff(const X<T>& x, const U& u)
{
    std::cout << (x.n + u) << std::endl;
}

So how should I define the template function doStuff() outside the class declaration?

Thanks in advance.


回答1:


Perhaps like this:

template <typename T>
class X {
public:
    X(int i) : n(i) {}

private:
    T n;

    template <typename U, typename V>
    friend void doStuff(const X<U>& x, const V& u);
};

template <typename U, typename V>
void doStuff(const X<U>& x, const V& u)
{
    std::cout << (x.n + u) << std::endl;
}

int main()
{
    X<int> x(1);
    doStuff(x, 3);
    X<double> y(1.0);
    doStuff(y, 3.5);
}



回答2:


@jrok gives a good solution.

Let's elaborate on why it works, and why it's required.

By declaring the function as

template <typename U, typename V>
friend void doStuff(const X<U>& x, const V& u);

You say that there is a function doStuff for each X and V. But you then ask, what about if U is not T? Well, when you call doStuff with an argument of type X, int, the only acceptable result of template argument deduction is to set the type T of the class definition to int.

Now, why does it not work to just do this:

template <typename V>
friend void doStuff(const X<T>& x, const V& u);

?

Actually, it kind of does. But what it means is that for any type T you tell the compiler that you are going to define a function that takes an X<T>, for any required T, and where the second parameter is a template parameter. Note, that the first argument is not a template function parameter.

There's no way to generically say 'whenever the user uses a class of type X<T>, use this specific pattern for how to define a function doStuff where X<T> is the first parameter.

So, in the class you promised that it would exist, but there's no way to write the definition in a templated fashion. it would have to be something like

template <typename T,typename U>
for_any_seen_template_instance_anywhere_in_the_program_< X<T> >:: 
      void doStuff(const X<U>& x, const V& u){
   ... code.
}

There's no such thing. Another way to think about it: When you write

doStuff(a,b); 

if the first parameter is not function template parameter, there's nothing being automatically generated with respect to that first argument. The template parameter types of class templates are not automatically deduced like template function parameters..

However, you can define X<T> for any required T (as you promised in the declaration) but you have to do it yourself for each required type:

template<typename V>
void doStuff(const X<int>& x, const V& u){
   std::cout << (x.n + u) << std::endl;
}

EDIT, answering the comment below.

It is true that all doStuff(X<U>,int) for example, are friends of any X<T> regardless of the types T and U. This means that inside the body of doStuff you could access the privates of objects of type X<Q>. In this case you did not pass any such objects into the function but you could make an X<std::string> in there and play around with it's privates. This is the price you pay for not going with the inline you had originally.



来源:https://stackoverflow.com/questions/12874958/how-to-define-a-friend-template-function-of-a-template-class-outside-of-its-decl

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!