1

我正在尝试编写一个类模板,该模板在具有不同模板类型的两个实例之间提供比较运算符。通常情况下,此操作员是非会员朋友。下面可以看到我试图实现的简化示例。

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>是私有的,因此朋友函数无法访问,我明白了原因。但是我该如何解决这个问题?在反向功能中添加友谊

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

进入 Wrapper 类模板体只会导致编译器产生歧义。我不想让 Wrapper 类的不同实例能够访问彼此的私有成员——我想限制对这个操作符的访问。这可能吗?

我的笔记本电脑因被关闭而处于危险之中,因此我和笔记本电脑(以及与此相关的窗口)都会接受任何想法。

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

物品数量:

  • 当您的类模板实例化一次 forX和一次 forY时,您有两个operator==.

  • 移出operator==类声明。

  • 请注意, afriend不是成员。因此访问冲突相关的诊断。

试试这个:

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==潜伏在那里的可能性......

于 2010-08-20T04:42:34.853 回答