请考虑以下代码:
#include <iostream>
class S {
static const int i = 42;
template <class T>
friend void f();
};
template <class T>
void f()
{
std::cout << S::i << "\n";
}
int main()
{
f<int>();
f<double>();
}
我想要的是允许访问类S
的私有部分到f<int>
,但不能访问f<double>
。即我想为'i' is a private member of 'S'
行获取f<double>()
之类的编译器错误。
如何实现这个目标?
答案 0 :(得分:8)
模板实例化是一个函数,所以只需命名它:void f<int>()
。
但您需要事先声明:
[C++03: 11.4/9 | C++11/C++14: 11.3/11]:
如果朋友声明出现在本地类(9.8)中并且指定的名称是非限定名称,则会查找先前声明,而不考虑最内部封闭非类作用域之外的作用域。对于朋友函数声明,如果没有事先声明,则程序格式错误。 [..]
(这不是你最初的friend
- inside-template-declaration的情况,因为在解析过程中稍后会查找模板。)
这是完成的解决方案:
#include <iostream>
template <class T>
void f();
class S {
static const int i = 42;
friend void f<int>();
};
template <class T>
void f()
{
std::cout << S::i << "\n";
}
int main()
{
f<int>();
f<double>();
}
现在唯一的错误是由f<double>()
电话引起的。
答案 1 :(得分:2)
您需要在类S
之前声明(或仅定义)模板函数。然后你可以说你希望它成为f<int>()
的朋友。像这样:
template <class T> void f();
class S {
static const int i = 42;
friend void f<int>();
};
template <class T>
void f()
{
std::cout << S::i << "\n";
}