由于种种原因,我想这样写代码:声明类模板为朋友
template<class T>
class C : public T
{
friend class T;
};
我认为的代码是清楚的。我想要一个类模板,它定义了从传递给它的类派生出的类作为模板参数,并且使事情变得更复杂一点,我想将基类定义为派生类的朋友。该代码似乎与MSVC编译器一致,但GNU C++编译器抱怨了很多。我应该怎么做才能获得所需的功能?
由于种种原因,我想这样写代码:声明类模板为朋友
template<class T>
class C : public T
{
friend class T;
};
我认为的代码是清楚的。我想要一个类模板,它定义了从传递给它的类派生出的类作为模板参数,并且使事情变得更复杂一点,我想将基类定义为派生类的朋友。该代码似乎与MSVC编译器一致,但GNU C++编译器抱怨了很多。我应该怎么做才能获得所需的功能?
它是格式不正确的,并且它不是有效的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;
};
为什么朋友,如果你是从它衍生出来的? – Nim
GCC具体说什么? –
@Nim:例如,您可能正在使用CRTP来实现模拟动态绑定,并且您需要相当于一个私有虚拟功能。也就是说,一个从基类中调用的函数,但不需要成为“类C”的公共接口的一部分。你可以说,“好吧,它不需要是私人的,只是不允许平民使用它”,这是真的,但是当你告诉他们(除了禁用默认拷贝)之外,有些人会非常激动, C++中的访问修饰符是完全浪费时间,你应该把所有东西都公开;-) –