5


0

このようなテンプレート化されたコンテナクラスがあります。

テンプレート<クラスKeyType、クラスValueType、クラスKeyCompareFunctor = AnObnoxiouslyLongSequenceOfCharacters、クラスValueCompareFunctor = AnObnoxiouslyLongSequenceOfCharacters>クラスMyClass {[...]}

つまり、このクラスのオブジェクトをインスタンス化するときには、いくつかの方法でそれを実行できます。

MyClass myObject; MyClass myObject; MyClass myObject;

それらはすべて良いです。 デフォルトではないバージョンのValueCompareFunctor引数を使用するMyClassをインスタンス化したいが、それでもKeyCompareFunctor引数のデフォルト値を使用したい場合に問題が生じます。 それから私はこれを書く必要があります:

MyClass、MyCustomValueCompareFunctor> myObject;

私がどういうわけか3番目の引数を省略して、単にこれを書くことができればそれははるかに便利でしょう:

MyClass myObject;

MyCustomValueCompareFunctorはMyValueType型のオブジェクトでのみ機能し、MyKeyType型のオブジェクトでは機能しないため、コンパイラは少なくとも理論的にはここで説明した内容を解決できたようです。

Cでこれを行う方法はありますか?

5 Answer


5


一般に、テンプレートと関数またはメソッドの両方で、Cは_trailing_パラメータに対してのみdefaultを使用することを許可し(したがって省略します)、それ以外の方法では使用できません。

テンプレートまたはマクロを使用して、 `+ AnObnoxiouslyLongSequenceOfCharacters `を ` Foo +`に短縮することをお勧めします-完全ではありませんが、何もないよりはましです。


4


No. 最も近い方法は、ユーザーが「+ void 」などのセンチネルタイプを指定できるようにすることです-「ここでデフォルト値を使用する」という意味で、クラス内でテンプレートメタマジックを使用して、「 void 」の場合は実際のデフォルトを「 typedef +」に設定しますあなたに与えられた。 しかし、これは読みやすさの観点からはおそらくお勧めできません。


3


http://www.boost.org/doc/libs/1_39_0/libs/parameter/doc/html/index.html[Boost parameters]およびhttp://www.boost.org/doc/libs/1_39_0/libs/ graph / doc / bgl_named_pa​​rams.html [ブーストグラフの名前付きパラメーター]はテンプレート関数/メソッドのパラメーターの命名に向けた努力です。 彼らはあなたが好む順番で引数を提供する機会を与えます。 一部の引数はオプションで、デフォルト値があります。

同じ方法がテンプレート引数にも適用できます。 N個のテンプレート引数をP個のオプション引数とする代わりに、N 1個のテンプレート引数を使用してクラスを作成してください。 最後のものは省略できる "名前付き"パラメータを保持します。

この答えはまだ完全ではありませんが、私はそれが良いスタートであることを願っています!


0


別の選択肢はTraitsクラスを使うことです:

テンプレートクラスKeyTraits {typedef AnObnoxiouslyLongSequenceOfCharacters比較; ;

テンプレートクラスValueTraits {typedef AnObnoxiouslyLongSequenceOfCharacters比較; ;

テンプレートクラスMyClass {typedef KeyTraits :: Compare KeyCompareFunctor; typedef ValueTraits :: Compare KeyCompareFunctor; ;

それで、もしあなたがキーのために異なる比較関数を必要とする型を持っているなら、あなたはその場合のために明示的にKeyTraits型を特殊化するでしょう。 これが `int`に変更された例です:

template <> class KeyTraits {typedef SpecialCompareForInt Cmopare; ;


0


継承を使用し、次のように機能するもう1つのオプションがあります。 最後の2つの引数では、必要な型を生成するために使用できる2つのメンバテンプレートを持つクラスから仮想的に継承するクラスを使用します。 継承は仮想的なので、宣言したtypedefは以下に示すように継承の間で共有されます。

template
class MyClass {
    typedef use_policies policies;

    typedef KeyType key_type;
    typedef ValueType value_type;
    typedef typename policies::
      template apply_key_compare::type
      key_compare;
    typedef typename policies::
      template apply_value_compare::type
      value_compare;
};

さて、あなたが使用するデフォルト引数を持ってください。それはあなたが提供したいデフォルト引数のためのtypedefを持っています。 メンバーテンプレートはキーと値の型によってパラメータ化されます

struct VirtualRoot {
  template
  struct apply_key_compare {
    typedef AnObnoxiouslyLongSequenceOfCharacters
      type;
  };
  template
  struct apply_value_compare {
    typedef AnObnoxiouslyLongSequenceOfCharacters
      type;
  };
};

struct DefaultArgument : virtual VirtualRoot { };

template struct KeyCompareIs : virtual VirtualRoot {
  template
  struct apply_key_compare {
    typedef T type;
  };
};

template struct ValueCompareIs : virtual VirtualRoot {
  template
  struct apply_value_compare {
    typedef T type;
  };
};

これで、 `+ use_policies `はすべてのテンプレート引数から派生します。 ` VirtualRoot +`の派生クラスがベースからメンバーを隠す場合、派生クラスのメンバーはベースのメンバーよりも支配的であり、ベースクラスメンバーが他のパスで到達できる場合でも使用されます継承ツリー。

タイプ `+ use_policies +`のオブジェクトを作成することは決してないので、仮想継承に対して支払いをしないことに注意してください。 優位ルールを利用するには仮想継承のみを使用します。

template
struct Inherit : B { };

template
struct use_policies : Inherit, Inherit
{ };

同じクラスから複数回派生する可能性があるため、クラステンプレート `+ Inherit +`を使用します。同じクラスを2回直接継承することは禁止されています。 しかし、間接的に継承することは許可されています。 これをすべて次のように使用できます。

MyClass m;
MyClass > > m;