模板友元

模板友元

函数模板与类模板的声明都可以在非局部类或类模板中使用friend说明符修饰(但只有函数模板可以定义在授予它友元权限的类或类模板中)。在这种情况下,所有特例化的模板都会成为一个友元,无论他是被隐式实例化、部分特例化或显式特例化。

1
2
3
4
5
6
7
class A {
template<typename T>
friend class B; // every B<T> is a friend of A

template<typename T>
friend void f(T) {} // every f<T> is a friend of A
};

友元声明不能用于部分特例化,但可以用于完全(显式)特例化:

1
2
3
4
5
6
7
template<class T> class A {}; // primary
template<class T> class A<T*> {}; // partial
template<> class A<int> {}; // full
class X {
template<class T> friend class A<T*>; // error!
friend class A<int>; // OK
};

当友元声明用于一个函数模板的完全特例化时,不能使用inline关键字和默认参数:

1
2
3
4
5
6
template<class T> void f(int);
template<> void f<int>(int);

class X {
friend void f<int>(int x = 1); // error: default args not allowed
};

模板友元运算符

模板友元的一个常见用途是声明一个非成员运算符重载其默认操作;例如,对用户定义的Foo<T>声明operator<<(std::ostream&, const Foo<T>&)

该运算符可以定义在类内部,这样的效果是为每一个类型T生成一个独立的非模板的operator<<,并使这个非模板的operator<<成为Foo<T>的友元。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>

template<typename T>
class Foo {
public:
Foo(const T& val) : data(val) {}
private:
T data;

// generates a non-template operator<< for this T
friend std::ostream& operator<<(std::ostream& os, const Foo& obj)
{
return os << obj.data;
}
};

int main()
{
Foo<double> obj(1.23);
std::cout << obj << '\n';
}

或者函数模板必须在类之前进行模板声明,在这种情况下Foo<T>之内的友元声明可使用类型T进行完全特例化的operator<<

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>

template<typename T>
class Foo; // forward declare to make function declaration possible

template<typename T> // declaration
std::ostream& operator<<(std::ostream&, const Foo<T>&);

template<typename T>
class Foo {
public:
Foo(const T& val) : data(val) {}
private:
T data;

// refers to a full specialization for this particular T
friend std::ostream& operator<< <> (std::ostream&, const Foo&);
// note: this relies on template argument deduction in declarations
// can also specify the template argument with operator<< <T>"
};

// definition
template<typename T>
std::ostream& operator<<(std::ostream& os, const Foo<T>& obj)
{
return os << obj.data;
}

int main()
{
Foo<double> obj(1.23);
std::cout << obj << '\n';
}

内容来自:https://en.cppreference.com/w/cpp/language/friend


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!