模板类的模板友元函数

tim*_*rau 5 c++ templates friend friend-function template-function

我有以下模板类和模板函数,它们打算访问类的私有数据成员:

#include <iostream>

template<class T>
class MyVar
{
    int x;
};

template<class T>
void printVar(const MyVar<T>& var)
{
    std::cout << var.x << std::endl;
}

template<class T>
void scanVar(MyVar<T>& var)
{
    std::cin >> var.x;
}

struct Foo {};

int main(void)
{
    MyVar<Foo> a;
    scanVar(a);
    printVar(a);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

为了将这两个函数声明为MyVar<T>友元函数,我在声明中尝试了以下方法template<class T> class MyVar来声明友元。它们都不起作用。我应该怎么做?

template<class T> friend void printVar(const MyVar&);
template<class T> friend void scanVar(MyVar&);
// compilation error

template<class T> friend void printVar(const MyVar<T>&);
template<class T> friend void scanVar(MyVar<T>&);
// compilation error

friend void printVar(const MyVar<T>&);
friend void scanVar(MyVar<T>&);
// link error

friend void printVar(const MyVar&);
friend void scanVar(MyVar&);
// link error too
Run Code Online (Sandbox Code Playgroud)

Mik*_*our 5

最简单的选择是在类中定义朋友:

template<class T>
class MyVar
{
    int x;

    friend void printVar(const MyVar & var) {
        std::cout << var.x << std::endl;
    }
    friend void scanVar(MyVar & var) {
        std::cin >> var.x;
    }
};
Run Code Online (Sandbox Code Playgroud)

缺点是这些函数只能通过依赖于参数的查找来调用。这在您的示例中不是问题,但如果它们没有合适的参数,或者您想指定名称而不调用它,则可能会出现问题。

如果你想要一个单独的定义,那么模板必须在类定义之前声明(所以它可用于朋友声明),但在之后定义(以便它可以访问类成员)。类也必须在函数之前声明。这有点乱,所以我只会展示两个函数之一:

template <typename T> class MyVar;
template <typename T> void printVar(const MyVar<T> & var);

template<class T>
class MyVar
{
    int x;

    friend void printVar<T>(const MyVar<T> & var);
};

template <typename T> void printVar(const MyVar<T> & var) {
    std::cout << var.x << std::endl;
}
Run Code Online (Sandbox Code Playgroud)