模板类的模板友元函数
template friend functions of template class
我有下面的模板类和模板函数,它们打算访问类的私有数据成员:
#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
的声明中尝试了以下方法来声明友元。它们都不起作用。我该怎么办?
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
最简单的选择是在类中定义友元:
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;
}
我设法得到了以下工作
#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讨论了"模板友元操作符"下的操作符的类似情况:
模板友元的一个常见用例是声明一个非成员作用于类模板的操作符重载。operator<<(std::ostream&, const Foo<T>&)
是用户自定义的Foo<T>
这样的操作符可以在类体中定义,其作用是为每个
T
和生成一个单独的非模板operator<<
使非模板operator<<
成为它的Foo<T>
的朋友…
或函数模板必须在在这种情况下,
,请参阅Foo<T>
中的友元声明可以关于T
operator<<
的完全专门化
这个在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;
}
有一个解决方案既简单又涉及到声明&好友函数的定义。在友元函数的声明中(在类内部),你必须给出与类接受的模板参数不同的模板参数(这是有意义的,因为这个函数不是这个类的成员)。
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) {
}
不需要前向声明,并且有一个声明&div定义。
相关文章:
- C++模板来检查友元函数的存在
- 如何使用单独文件中的派生类访问友元函数对象
- 模板化的类和友元函数
- 友元函数无法访问私有数据成员 (c++)
- 继承和友元函数,从基类访问受保护的成员
- 如何在友元函数中使用静态成员而不添加前缀 [类名]::
- 在将函数声明为友元时,尖括号的含义是什么?
- 在模板类之外定义友元函数的正确方法是什么?
- 2个模板化类的非模板友元函数未定义引用错误
- C++ 友元函数和私有构造函数
- 使第二个类的构造函数成为第一个类中的友元函数
- 未定义的类模板不会实例化以检查友元函数
- C++类中的友元函数有问题?
- 使用typedef'ed返回类型声明友元函数时出现编译器错误
- 模板类中的模板友元函数
- C++ 17 个友元函数声明和内联命名空间
- 将派生类的构造函数声明为父类的友元
- 友元函数需要一个帮助程序函数
- 在基/派生类的成员函数/友元函数中派生* 到 Base* 的转换
- 模板类的非模板函数友元