限制类的模板朋友

时间:2016-03-09 15:18:37

标签: c++ templates friend

请考虑以下代码:

#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>()之类的编译器错误。

如何实现这个目标?

2 个答案:

答案 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>()电话引起的。

live demo

答案 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";
}