1

テンプレートの種類が異なる 2 つのインスタンス間の比較演算子を提供するクラス テンプレートを作成しようとしています。よくあることですが、このオペレーターは非会員の友人です。私が達成しようとしていることの簡単な例を以下に示します。

template<typename T>
class Wrapper {
  // Base type, which must have a val() method to allow comparison
  T t_;
public:
  Wrapper(const T& t) : t_(t) {}

  // Comparison operator
  template<typename B>
  friend
  bool
  operator==(const Wrapper &a, const Wrapper<B>&b) {
    return a.t_.val()==b.t_.val();
  }
};

// First example type for Wrapper
class X {
  int x_;    
public:
  X(int x) : x_(x) {}

  int
  val() const {return x_;}
};

// Second example type for Wrapper
class Y {
  int y_;
public:
  Y(int y) : y_(y) {}

  int
  val() const {return 2*y_;}
};

int
main() {
  Wrapper<X> WX(X(4));
  Wrapper<Y> WY(Y(2));
  return WX==WY ? 1 : 0;
}

この例 (g++ 4.4.0) はコンパイルされません。代わりに、y_fromWrapper<Y>がプライベートであり、friend 関数にアクセスできないと不平を言います。その理由はわかります。しかし、どうすればこれを修正できますか? 逆関数に友情を追加する

  template<typename B>
  friend bool operator==(const Wrapper<B> &, const Wrapper &);

Wrapper クラスのテンプレート本体に挿入すると、コンパイラにあいまいさが生じるだけです。Wrapper クラスの異なるインスタンスが互いのプライベート メンバーにアクセスできるようにしたくありません。この 1 つのオペレーターへのアクセスを制限したいのです。これは可能ですか?

私のラップトップは脱気の危険にさらされているので、どんなアイデアでも私とラップトップ (そしてそのウィンドウ) の両方に喜ばれるでしょう。

4

2 に答える 2

2

私のラップトップは(今のところ)安全です。C++ FAQ-liteを読み直すと役に立ちましたが、この例は最初は私自身の問題と一致していないようでした。以下は、演算子の定義をテンプレートクラス本体の外に移動することによって機能します。

template <typename T> class Wrapper;

template<typename A, typename B>
inline
bool
operator==(const Wrapper<A> &a, const Wrapper<B>&b) {return a.t_.val()==b.t_.val();}

template<typename T>
class Wrapper {
  T t_;
public:
  Wrapper(const T& t) : t_(t) {}

  template<typename A, typename B>
  friend
  bool
  operator==(const Wrapper<A> &a, const Wrapper<B>&b);
};

よりエレガントで洞察に満ちた提案をいただければ幸いです。

于 2010-08-20T04:40:52.050 に答える
2

ものの数:

  • クラステンプレートがに対してX1回ずつインスタンス化されるY場合、の2つの定義がありoperator==ます。

  • operator==クラス宣言の外に移動します。

  • friendaはメンバーではないことに注意してください。したがって、アクセス違反に関連する診断。

これを試して:

template<typename T>
class Wrapper {
  // Base type, which must have a val() method to allow comparison
  T t_;
public:
  Wrapper(const T& t) : t_(t) {}

  // Comparison operator

  template<typename A, typename B>
  friend bool
  operator==(const Wrapper<A> &a, const Wrapper<B>&b);
};

template<typename A, typename B>
  bool
  operator==(const Wrapper<A> &a, const Wrapper<B>&b) {
    return a.t_.val()==b.t_.val();
  }

// First example type for Wrapper
class X {
  int x_;    
public:
  X(int x) : x_(x) {}

  int
  val() const {return x_;}
};

// Second example type for Wrapper
class Y {
  int y_;
public:
  Y(int y) : y_(y) {}

  int
  val() const {return 2*y_;}
};

int
main() {
  Wrapper<X> WX(X(4));
  Wrapper<Y> WY(Y(2));
  return ::operator==(WX, WY) ? 1 : 0;
}

friend operator==私はまだそこに2つの可能性が潜んでいる可能性が好きではありませんが...

于 2010-08-20T04:42:34.853 に答える