模板类的模板友元函数

时间:2015-05-25 13:43:07

标签: c++ templates friend friend-function template-function

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

Data

要将这两个函数声明为#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; } 的朋友函数,我已在MyVar<T>的声明中尝试了以下方式来声明友谊。它们都不起作用。我该怎么办?

template<class T> class MyVar

4 个答案:

答案 0 :(得分:4)

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

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;
    }
};

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

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

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;
}

答案 1 :(得分:2)

我成功完成了以下工作

#include <iostream>

template<class T>
class MyVar;

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

template<class T>
void scanVar(MyVar<T>& var);

template<class T>
class MyVar
{
    int x;
    friend void printVar<T>(const MyVar<T>& var);
    friend void scanVar<T>(MyVar<T>& var);
};

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;
}

UPD http://en.cppreference.com/w/cpp/language/friend在&#34;模板朋友运营商&#34;

下与运营商谈论类似案例
  

模板朋友的常见用例是非成员的声明   作用于类模板的运算符重载,例如   operator<<(std::ostream&, const Foo<T>&)用于某些用户定义的   Foo<T>

     

这样的运算符可以在类体中定义,具有效果   为每个operator<<生成单独的非模板T   使非模板operator<<成为其Foo<T>

的朋友      

...

     

或函数模板必须在之前声明为模板   类主体,在这种情况下Foo<T>中的朋友声明可以   请参阅operator<<

的完整专业化T

答案 2 :(得分:1)

这个编译在MSVC2013上。基本上在朋友

之前将前向声明添加到类和函数中
template<class T>   class MyVar ; // class forward declaration

template<class T> ; // function forward declarations
void printVar(const MyVar<T>& var);
template<class T>
void scanVar(MyVar<T>& var);

template<class T>
class MyVar
{
    friend void printVar<T>(const MyVar<T>&);
    friend void scanVar<T>(MyVar<T>&);
    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 main1(void)
{
    MyVar<Foo> a;
    scanVar(a);
    printVar(a);
    return 0;
}

答案 3 :(得分:1)

有一种解决方案,既简单又涉及到将好友函数的声明与定义分开。在Friend函数的声明中(在类内部),您必须提供与该类接受的模板不同的模板参数(这是有道理的,因为该函数不是该类的成员)。

template<class T>
class MyVar
{
    int x;

    template<typename Type>
    friend void printVar(const MyVar<Type> & var);

    template<typename Type>
    friend void scanVar(MyVar<Type> & var);
};

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

}

template<typename T>
void scanVar(MyVar<T> & var) {

}

不需要前向声明,并且声明和定义是分开的。