C++ Templates: Partial Template Specifications and Friend Classes

别来无恙 提交于 2019-12-05 03:34:51

In C++, you can grant access beyond private on four levels.

  • completely public access (see pmr's answer)
  • access within inheritance hierarchy (protected, irrelevant here)
  • to a base template friend (see this answer)
  • to a non-template or fully specialized friend (too weak to solve your use case)

There is no middle way between the two latter kinds of friendship.

From §14.5.4 of the C++ standard:.

Friend declarations shall not declare partial specializations.

The following declaration will allow you to implement what you need. It gives you a free hand to access any specialization of your template from any other specialization, but still only within X. It is slightly more permissive than what you asked for.

template<class T> class X
{
    template<class Any> friend class X;
    public:
        ...
};

We can define a getter protected by a key defined in 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;
}

This still has some weakness. Everybody with an X<T*> can now use get. But this is so obfuscated by now, that no one is goiing to realize that. I'd choose a simple public getter.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!