9

どういうわけか部分的なテンプレート仕様をフレンドクラスにすることは可能ですか?つまり、次のテンプレートクラスがあると考えてください

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

これで、たとえばポインタの部分的な特殊化ができました

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

私が達成したいのは、可能な限りすべてのX<T*>人の友達クラスであるということです。つまり、の友達である必要があります。X<S>SX<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 ++では、4つのレベルを超えてアクセスを許可できprivateます。

  • 完全にpublicアクセスする(pmrの回答を参照)
  • 継承階層内のアクセス(protected、ここでは無関係)
  • 基本テンプレートへfriend(この回答を参照)
  • 非テンプレートまたは完全に専門化されたfriendもの(ユースケースを解決するには弱すぎる)

後者の2種類の友情の間には中道はありません。

C ++標準の§14.5.4から:。

フレンド宣言は、部分的な専門分野を宣言してはなりません。

次の宣言により、必要なものを実装できます。これにより、他のスペシャライゼーションからテンプレートのスペシャライゼーションにフリーハンドでアクセスできますが、それでも内にのみアクセスできますX。それはあなたが求めたものよりもわずかに寛容です。

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

getterXで定義されたキーで保護を定義できます。

#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 に答える