22

タイプ std::string の属性を持つクラスがあります。属性を比較することで、クラスに <、>、==、<=、>= などの比較演算子関数を提供したいと考えています。

私の質問は次のとおりです。簡単な方法またはツール

(1) 演算子 < (および ==) 用の関数など、1 つまたは 2 つの関数を記述するだけで、他の関数は自動的に生成されます。

std::string(2)クラス比較は、比較関数がすでに提供されているタイプの属性に依存しているため、さらに単純です。

4

4 に答える 4

27

不思議なことに繰り返されるテンプレート パターン

この場合、必要なすべての演算子を実装し、単純に継承する単純な基本クラスを提供します。

template <class T>
struct implement_relational_operators{
    friend bool operator<=(const T & a,const T & b){ return a < b || a == b; }
    friend bool operator>(const T &  a, const T & b){ return !(a <= b); }
    friend bool operator!=(const T &  a, const T & b){ return !(a == b);}
    friend bool operator>=(const T &  a, const T & b){ return !(a < b); }
};

template <class T>
struct scalar : public implement_relational_operators<scalar<T> >{
    T value;
    bool operator<(const scalar& o) const { return value < o.value;}
    bool operator==(const scalar& o) const { return value == o.value;}
};

std::rel_opsこれは(以下を参照)の欠点を共有しません。ただし、 と を実装する必要がありoperator<ますoperator==。同様のトリックが によって使用されboostます。

C++20 では<=>、状況がさらに改善される可能性があります (以下を参照)。

std::rel_ops(C++20 では非推奨)

std::rel_opsは、 に基づく追加の操作を提供する<ため==、2 つの演算子を記述するだけで済みます。

ただし、C++ 20 では非推奨になりa <=> b、ミックスにスローされます。

要件

operator=等値 ( ) とより小さい ( operator<) 比較演算子だけが必要です。std::rel_ops以下が成り立つので、残りは で自動的に生成できます。

a != b equal to !(a == b)
a <= b equal to (a < b) || (a == b)
a >= b equal to !(a < b)
a >  b equal to !(a <= b)

これらは手書きよりも効率が悪いことに注意してください。

警告

ただし、これらの演算子を自分で提供するのは簡単なので、余分な労力をかけてそれらを作成する必要があります。また、 R. Martinho Fernandesが述べているように、いくつかの欠点もあります。

次の場合を除き、[それら] は適切に機能しないことに注意してください。

  1. using namespace std::rel_ops演算子を使用するすべてのコンテキストに追加します。また
  2. using::operator!=; using::operator<=; using::operator>=; using::operator>;クラスの名前空間に追加します (クラスusing namespace std::rel_opsの名前空間では、ADL によって取得されないため、受け入れられません)。
于 2012-12-17T16:20:51.123 に答える
8

を使用できますstd::rel_opsが、それは間違っています。それは、誰のツールキットにも属さないハンマーです。

通常のアプローチは、クラスの詳細を定義operator==operator<、その知識を使用することです。残りの 4 つの演算子は、次のように記述できます。

a != b!(a == b)

a <= b!(b < a)

a > bb < a

a >= b!(a < b)

于 2012-12-17T16:33:19.653 に答える
5

1つのオプションは、BartonNackmanトリックなどのCRTPを使用することです。

https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern

https://en.wikipedia.org/wiki/Barton%E2%80%93Nackman_trick

// A class template to express an equality comparison interface.
template<typename T> class equal_comparable {
    friend bool operator==(T const &a, T const &b) { return  a.equal_to(b); }
    friend bool operator!=(T const &a, T const &b) { return !a.equal_to(b); }
};

class value_type
 // Class value_type wants to have == and !=, so it derives from
 // equal_comparable with itself as argument (which is the CRTP).
 : private equal_comparable<value_type> {
  public:
    bool equal_to(value_type const& rhs) const; // to be defined
};
于 2012-12-17T16:29:18.463 に答える