2011-10-26 102 views
4

由于种种原因,我想这样写代码:声明类模板为朋友

template<class T> 
class C : public T 
{ 
friend class T; 
}; 

我认为的代码是清楚的。我想要一个类模板,它定义了从传递给它的类派生出的类作为模板参数,并且使事情变得更复杂一点,我想将基类定义为派生类的朋友。该代码似乎与MSVC编译器一致,但GNU C++编译器抱怨了很多。我应该怎么做才能获得所需的功能?

+4

为什么朋友,如果你是从它衍生出来的? – Nim

+1

GCC具体说什么? –

+1

@Nim:例如,您可能正在使用CRTP来实现模拟动态绑定,并且您需要相当于一个私有虚拟功能。也就是说,一个从基类中调用的函数,但不需要成为“类C”的公共接口的一部分。你可以说,“好吧,它不需要是私人的,只是不允许平民使用它”,这是真的,但是当你告诉他们(除了禁用默认拷贝)之外,有些人会非常激动, C++中的访问修饰符是完全浪费时间,你应该把所有东西都公开;-) –

回答

6

它是格式不正确的,并且它不是有效的C++,虽然它在MSVC中有效。 C++ 03标准说明了这一点(7.1.5.3§2):

3.4.4描述名称查找如何在标记符在详细类型说明符中进行。如果标识符解析为类名称 或枚举名称,则详细类型说明符将其引入到 声明中,这与简单类型说明符介绍它的 类型名称的方式相同。如果标识符解析为typedef名称或模板 type-parameter,则详细说明类型说明符不合格。 [注: 这意味着,类模板与模板 类型参数T,申报

 friend class T; 

内是非法的构造。 ]如果名称查找未找到名称的声明,则详细类型说明符格式不正确,除非它是简单形式类别密钥标识符,在这种情况下,标识符为3.335.1中所述声明的 。

出于同样的原因,您不能像friend class std::string;这样做,但您必须与模板参数联系std::basic_string

然而新的C++ 11规范允许朋友们宣布了新的语法,这简直就是(N3242的11.3§3):

friend <typename-specifier>; 

这种新的语法允许你做你想做的(我不知道MSVC是否支持这个):

template<typename T> 
class C : public T 
{ 
    friend T; 
};