将模板参数设为朋友?

时间:2009-03-31 19:23:03

标签: c++ templates friend

示例:

template<class T>
class Base {
public:
    Base();
    friend class T;
};

现在这不起作用......有没有办法做到这一点?

我实际上正在尝试制作这样的通用类封口机:

class ClassSealer {
private:
   friend class Sealed;
   ClassSealer() {}
};
class Sealed : private virtual ClassSealer
{ 
   // ...
};
class FailsToDerive : public Sealed
{
   // Cannot be instantiated
};

我在这个网站上找到了这个例子,但我找不到它......(here

我知道有other ways这样做但刚才我很好奇你是否真的可以这样做。

3 个答案:

答案 0 :(得分:39)

标准中明确禁止使用它,即使某些版本的VisualStudio允许它。

C ++标准7.1.5.3详细说明的类型说明符,第2段

  

3.4.4描述了如何对标识符进行名称查找   阐述了式说明符。如果   标识符解析为   一个类名或枚举名,   精心设计的说明者介绍   它进入宣言同样如此   简单类型说明符引入的方式   它的类型名称。如果标识符解析   到typedef-name或   模板类型参数,   精心设计的说明符是   病态的。 [注意:这意味着,   在带有的一个类模板中   模板类型参数T,   声明朋友类T ;是   病态的。 ]

我认为上面的代码是一个密封(禁止扩展)类的模式。还有另一个解决方案,它不会真正阻止扩展,但会标记从类中不加扩展。如ADOBE Source Library中所示:

namespace adobe { namespace implementation {
template <class T>
class final
{
protected:
   final() {}
};
}}
#define ADOBE_FINAL( X ) private virtual adobe::implementation::final<T>

用法:

class Sealed : ADOBE_FINAL( Sealed )
{//...
};

如果你真的强迫它,它允许扩展:

class SealBreaker : public Sealed, ADOBE_FINAL( Sealed )
{
public:
   SealBreaker() : adobe::implementation::final<Sealed>(), Sealed() {}
};

它会限制用户误做。

编辑

即将推出的C ++ 11标准允许您使用稍微不同的语法与类型参数建立联系:

template <typename T>
class A {
   // friend class T; // still incorrect: elaborate type specifier
   friend T;          // correct: simple specifier, note lack of "class"
};

答案 1 :(得分:20)

我发现了一个简单的技巧,可以将模板参数声明为朋友:

template < typename T>
struct type_wrapper 
{ 
   typedef T type; 
}; 


template < typename T> class foo 
{ 
  friend class type_wrapper < T>::type 
};   // type_wrapper< T>::type == T

但是我不知道这有助于定义类封口机的替代版本。

答案 2 :(得分:3)

你真的需要这样做吗? 如果您想阻止某人从您的类派生,只需添加注释并使析构函数非虚拟。