代码之家  ›  专栏  ›  技术社区  ›  beldaz Nicolas W.

一类模板两种实例化的C++好友比较

  •  1
  • beldaz Nicolas W.  · 技术社区  · 14 年前

    我正在尝试编写一个类模板,它在具有不同模板类型的两个实例之间提供比较运算符。与通常情况一样,此运算符是非成员朋友。下面是我试图实现的一个简单示例。

    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_ Wrapper<Y> 是私密的,对朋友来说是不可接近的,我明白为什么。但我该怎么解决这个问题呢?为反向函数添加友谊

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

    到包装类模板体中只会对编译器造成歧义。我不想允许包装类的不同实例彼此访问私有成员-我想限制对此运算符的访问。这有可能吗?

    我的笔记本电脑有被排挤的危险,所以任何想法都会被我和笔记本电脑(以及相关窗口)所吸引。

    2 回复  |  直到 14 年前
        1
  •  2
  •   dirkgently    14 年前

    数量:

    • 当类模板被实例化一次 X 一次 Y ,您有两个定义 operator== .

    • 移动 运算符== 类外声明。

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

    试试这个:

    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;
    }
    

    尽管我还是不喜欢有两种可能 朋友 运算符== 潜伏在那里…

        2
  •  2
  •   beldaz Nicolas W.    14 年前

    我的笔记本电脑现在可以安全地重新阅读了 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);
    };
    

    任何更优雅或更有洞察力的建议都会受到赞赏。