9

是否有可能以某种方式使部分模板规范成为朋友类?即考虑你有以下模板类

template <class T> class X{
    T t;
};

现在你有了部分特化,例如指针

template <class T> class X<T*>{
    T* t;
};

我想要完成的是,每一个可能X<T*>都是X<S>for ANY的朋友类S。即X<A*>应该是的朋友X<B>

当然,我想到了 X 中常用的模板友元声明:

template <class T> class X{
    template <class S> friend class X<S*>;
}

但是,这不会编译,g++ 告诉我:

test4.cpp:34:15:错误:“ template<class T> class X”的特化必须出现在命名空间范围内

test4.cpp:34:21:错误:部分特化“ X<S*>”声明为“朋友”

这根本不可能,还是有一些解决方法?

我问的原因是我需要一个构造函数来X<T*>从任意创建此类X<S>S必须是 的子类型T)。

代码如下所示:

template <class T> class X<T*>{
    T* t;

    template<class S>
    X(X<S> x) : t(&(x.t))  {} //Error, x.t is private
}

现在,编译器当然会抱怨,这x.t在构造函数中是不可见的,因为它是私有的。这就是为什么我需要一个部分专业化的朋友班。

4

2 回答 2

8

在 C++ 中,您可以授予超过private四个级别的访问权限。

  • 完全public访问(见 pmr 的回答)
  • 继承层次结构中的访问(protected这里无关)
  • 到基本模板friend(请参阅此答案)
  • 到非模板或完全专业化friend(太弱而无法解决您的用例)

后两种友谊之间没有中间道路。

来自 C++ 标准的 §14.5.4:。

友元声明不得声明部分特化。

以下声明将允许您实现所需的内容。它使您可以自由地从任何其他专业化访问模板的任何专业化,但仍仅限于X. 它比您要求的要宽松一些。

template<class T> class X
{
    template<class Any> friend class X;
    public:
        ...
};
于 2012-06-15T08:11:25.497 回答
1

我们可以定义一个getter由 X 中定义的密钥保护的。

#include <type_traits>

template <class T> class X{
  T t;
public:
  struct Key {
    template<typename S>
    Key(const X<S>&) {
      static_assert(std::is_pointer<S>::value, "Not a pointer");
    }
  };

  const T& get(Key) const { return t; }
  T& get(Key) { return t; }
};

template <class T> class X<T*> {
  T* t;
public:
  template<class S>
  X(X<S>& x) : t(&(x.get(typename X<S>::Key(*this))))  {}
};

int main()
{
  X<int> x1;
  X<int*> x2(x1);
  return 0;
}

这仍然有一些弱点。现在每个人都X<T*>可以使用 get. 但这现在太模糊了,没有人会意识到这一点。我会选择一个简单的公共吸气剂。

于 2012-06-15T08:21:58.203 回答