3

オプションでコンテンツを適切に定義された順序で維持できる、テンプレート化された C++ 汎用コンテナー クラスを作成しています。以前は関数ポインターを使用して、適切な型固有の方法で内容を並べ替えていましたが、代わりにテンプレート化されたファンクター引数を使用するように変更しようとしています。

クラスのユーザーが同じタイプの項目を異なるコンテナーで異なる方法でソートしたままにしたい場合がよくあるため、コンテナー クラスは、ユーザーがオプションで独自の比較ファンクターを指定できるようにするオプションのテンプレート引数を取ります。

template <class ItemType, class CompareFunctorType = CompareFunctor<ItemType> > class MyContainer
{
    [...]
};

クラス ユーザーがカスタム ファンクター タイプを指定しない場合、デフォルトで次の CompareFunctor 定義が使用されます。

template <typename ItemType> class CompareFunctor
{
public:
    bool IsItemLessThan(const ItemType & a, const ItemType & b) const
    {
       return (a<b);   // will compile only for types with < operator
    }
};

これは、組み込み型と、より小演算子が定義されているユーザー定義型でうまく機能します。ただし、組み込みまたは明示的に定義された小なり演算子がないタイプでも自動的に機能するようにしたいと思います。これらのタイプの場合、コンテナー内の項目の順序は重要ではありません。

動機は、私がこのコンテナーを使用して多くの異なる型を保持することです。ほとんどの場合、コンテナー内の型の順序は気にしませんが、場合によっては気にします...そして私は気にしません'このコンテナー クラスで使用できるように、これらのさまざまな型すべてに「ダミーの」小なり演算子を追加する必要はありません...そして、カスタムの「ダミー」を明示的に指定する必要はありません。 「より小さい演算子を持たない項目を格納するためにテーブルを使用するたびに、CompareFunctor 引数。

したがって、可能な限りデフォルトの CompareFunctor (上記) が使用されるようにテンプレートの特殊化 (または何か) を使用できる方法はありますが、CompareFunctor がエラーを引き起こす場合、C++ は自動的に「ダミー」にフォールバックします。下のような FallbackCompareFunctor ?それとも、このジレンマを処理するための他の賢い方法はありますか?

template <typename ItemType> class FallbackCompareFunctor
{
public:
    bool IsItemLessThan(const ItemType & a, const ItemType & b) const
    {
       return ((&a)<(&b));   // will compile for all types (useful for types where the ordering is not important)
    }
};
4

4 に答える 4

1

デフォルトのソートされていないケースでは、すべてのケースでfalseを返すだけのNull比較ファンクターを使用します。
次に、std :: less()ファンクターを使用して、テンプレートをソートされたコンテナーに特化できます。

       template<class T>
       struct NullCompare: public binary_function <T, T, bool> 
       {
          bool operator()(const T &l, const T &r) const
          {
              // edit: previously had "return true;" which is wrong.
              return false;
          }
       };

       template <class T, class Compare=NullCompare<T> > 
       class MyContainer
       {
           [...]
       };

       template <class T, class Compare=std::less<T> > 
       class MySortedContainer : public MyContainer<T, Compare>
       {
           [...]
       };
于 2009-07-26T01:40:04.240 に答える
1

Eugene の回答に基づいて Google 検索を行っているときに、次の記事を見つけました。

http://www.martinecker.com/wiki/index.php?title=Detecting_the_Existence_of_Operators_at_Compile-Time

おそらく、そこに提示されたコードを適応させることができます...

于 2009-07-26T02:59:45.030 に答える
0

boost::enable_ifは、コンパイル時の評価に基づいて、テンプレートの特殊化をオンまたはオフにすることができます。

チェックしている型に lessthan 演算子がない場合にコンパイル時に false と評価される構造を作成できる場合は、それを使用して、CompareFunctor::IsItemLessThan のフォールバック特殊化を有効にすることができます。

template <typename ItemType> class CompareFunctor
{
public:
    bool IsItemLessThan(const ItemType & a, const ItemType & b) const
    {
       return OptionalLessThan<ItemType>(a, b); 
    }
};

template<class T> 
typename boost::enable_if<some_condition<T>, bool>::type 
OptionalLessThan(const T& a, const T& b)
{
    return ((&a)<(&b)); 
}

template<class T> 
typename boost::disable_if<some_condition<T>, bool>::type 
OptionalLessThan(const T& a, const T& b)
{
    return a < b; 
}

もちろん、何らかの方法で演算子lessthanをチェックするためにsome_conditionも必要です...boost::type_traitsとMPLコードを見てください-それらは同様のことをします。

于 2009-07-26T02:11:45.090 に答える