2009-03-22 17 views
4

私は、演算子!=><=、および>=をサポートする必要があるいくつかのクラスを設計中です。これらの演算子は、演算子==<の観点から実装されます。関係演算子の実装のジレンマ

この段階では、継承の間に選択し、消費者にstd::rel_ops²を「手動で」強制する必要があります。

[1]継承(可能な実装):

template<class T> class RelationalOperatorsImpl 
{ 
    protected: 
    RelationalOperatorsImpl() {} 
    ~RelationalOperatorsImpl() {} 

    friend bool operator!=(const T& lhs, const T& rhs) {return !(lhs == rhs);} 
    friend bool operator>(const T& lhs, const T& rhs) {return (rhs < lhs);} 
    friend bool operator<=(const T& lhs, const T& rhs) {return !(rhs < lhs);} 
    friend bool operator>=(const T& lhs, const T& rhs) {return !(lhs < rhs);} 
}; 

template<typename T> class Foo : RelationalOperatorsImpl< Foo<T> > 
{ 
    public: 
    explicit Foo(const T& value) : m_Value(value) {} 

    friend bool operator==(const Foo& lhs, const Foo& rhs) {return (lhs.m_Value == rhs.m_Value);} 
    friend bool operator<(const Foo& lhs, const Foo& rhs) {return (lhs.m_Value < rhs.m_Value);} 

    private: 
    T m_Value; 
}; 

[2] std::rel_opsのり:

template<typename T> class Foo 
{ 
    public: 
    explicit Foo(const T& value) : m_Value(value) {} 

    friend bool operator==(const Foo& lhs, const Foo& rhs) {return (lhs.m_Value == rhs.m_Value);} 
    friend bool operator<(const Foo& lhs, const Foo& rhs) {return (lhs.m_Value < rhs.m_Value);} 

    private: 
    T m_Value; 
}; 

void Consumer() 
{ 
    using namespace std::rel_ops; 

    //Operators !=, >, >=, and <= will be instantiated for Foo<T> (in this case) on demand. 
} 

私は基本的には、コードの重複を避けるためにしようとしています。どちらの方法が「感じる」という考えはどんな考えですか?

答えて

5

boostを使用していて、あなたのクラスをboost::less_than_comparable<T>boost::equality_comparable<T>から継承したことがありますか?あなたの最初の提案に似ていますが、いくつかの長所と短所があります。長所:コードの重複を避ける。短所:ブーストへの依存を作成します。

boostは非常に一般的なC++ライブラリです(まだ使用していない場合は、使用を真剣に検討する必要があります)、con因子は淡色表示されます。

+0

これは優れた提案です。ブーストは決して私を驚かせることを止めません。私は答えを受け入れる前に、他の人から聞きたいのですが。 ;) –

1

私はstd::rel_opsがかなりいいですが、最初に考慮すべきことがあります。std::rel_opsは、同じタイプの2つのパラメータを受け入れるテンプレート関数として演算子を提供します。テンプレート引数の控除が発生すると、ほとんどのコンバージョン(算術宣伝やユーザー定義コンバージョンなど)は実行されないため、このような追加の演算子(たとえば!=)を使用することはできません。

など。あなたは、通常の整数のように動作しようとするクラスMyIntを持っている場合、あなたはしかし

MyInt x, y; 

x < 5; 
9 == x; 

を行うことができるように、

x > 5; 
30 <= x; 

はないでしょう変換関数/コンストラクタやテンプレートの演算子を書かれているかもしれません(std::rel_opsで)2つの引数が異なる型であるため、テンプレート引数の減算が失敗するためです。

関連する問題