簡體   English   中英

C ++:除最后一個之外的模板參數的默認值?

[英]C++: Default values for template arguments other than the last ones?

我有我的模板化容器類,如下所示:

template<
   class KeyType, 
   class ValueType, 
   class KeyCompareFunctor   = AnObnoxiouslyLongSequenceOfCharacters<KeyType>, 
   class ValueCompareFunctor = AnObnoxiouslyLongSequenceOfCharacters<ValueType> 
>
   class MyClass
   {
      [...]
   }

這意味着當我實例化這個類的對象時,我可以通過幾種不同的方式來實現:

MyClass<MyKeyType, MyValueType> myObject;
MyClass<MyKeyType, MyValueType, MyCustomKeyCompareFunctor> myObject;
MyClass<MyKeyType, MyValueType, MyCustomKeyCompareFunctor, MyCustomValueCompareFunctor> myObject;

這些都很好。 當我想要實例化使用ValueCompareFunctor參數的非默認版本的MyClass時,問題出現了,但我仍然想使用KeyCompareFunctor參數的默認值。 然后我要寫這個:

MyClass<MyKeyType, MyValueType, AnObnoxiouslyLongSequenceOfCharacters<MyKeyType>, MyCustomValueCompareFunctor> myObject;

如果我能以某種方式省略第三個參數並且只寫下這個會更方便:

MyClass<KeyType, ValueType, MyCustomValueCompareFunctor> myObject;

由於MyCustomValueCompareFunctor僅適用於MyValueType類型的對象,而不適用於MyKeyType類型的對象,因此編譯器似乎至少在理論上可以解決我的意思。

有沒有辦法在C ++中執行此操作?

通常,在模板和函數或方法中,C ++都允許您使用默認值(從而省略)僅跟蹤參數 - 沒有出路。

我建議使用模板或宏來縮短AnObnoxiouslyLongSequenceOfCharacters<MyKeyType>Foo<MyKeyType> - 不完美,但總比沒有好。

號你能來最接近的是允許用戶指定一些定點類型-像void - “在這里使用默認值”的含義,並使用模板超魔類里面typedef真正的默認值,如果void是給你的。 但從可讀性的角度來看,這可能不是一個好主意。

Boost參數Boost圖形命名參數是為模板函數/方法命名參數的努力。 他們提供了以您喜歡的順序提供參數的機會。 一些參數可以是可選的,具有默認值。

相同的方法可以應用於模板參數。 而不是使用N個模板參數+ P個可選參數,使用N + 1模板參數創建您的類。 最后一個將保存“命名”參數,可以省略。

這個答案還沒有完成,但我希望這是一個好的開始!

另一種選擇是使用Traits類:

template <class KeyType>
class KeyTraits
{
  typedef AnObnoxiouslyLongSequenceOfCharacters<KeyType> Compare;
};

template <class ValueType>
class ValueTraits
{
  typedef AnObnoxiouslyLongSequenceOfCharacters<ValueType>  Compare;
};

template<class KeyType class ValueType>
class MyClass
{
  typedef KeyTraits<KeyType>::Compare KeyCompareFunctor;
  typedef ValueTraits<ValueType>::Compare KeyCompareFunctor;
};

然后,如果你有一個需要Key的不同比較函數的類型,那么你明確地專門針對那種情況使用KeyTraits類型。 這是我們為int更改它的示例:

template <>
class KeyTraits<int>
{
  typedef SpecialCompareForInt Cmopare;
};

還有另一個選項,它使用繼承,其工作方式如下。 對於最后兩個參數,它使用一個類,該類實際上從具有兩個成員模板的類繼承,可用於生成所需的類型。 因為繼承是虛擬的,所以它聲明的typedef在繼承之間共享,如下所示。

template<class KeyType, 
         class ValueType, 
         class Pol1 = DefaultArgument, 
         class Pol2 = DefaultArgument>
class MyClass {
    typedef use_policies<Pol1, Pol2> policies;

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

現在,有一個您使用的默認參數,它具有您想要提供的默認參數的typedef。 成員模板將通過鍵和值類型進行參數化

struct VirtualRoot { 
  template<typename KeyType>
  struct apply_key_compare {
    typedef AnObnoxiouslyLongSequenceOfCharacters<KeyType> 
      type;
  };
  template<typename ValueType>
  struct apply_value_compare {
    typedef AnObnoxiouslyLongSequenceOfCharacters<ValueType> 
      type;
  };
};

struct DefaultArgument : virtual VirtualRoot { };

template<typename T> struct KeyCompareIs : virtual VirtualRoot {
  template<typename KeyType>
  struct apply_key_compare {
    typedef T type;
  };
};

template<typename T> struct ValueCompareIs : virtual VirtualRoot {
  template<typename ValueType>
  struct apply_value_compare {
    typedef T type;
  };
};

現在, use_policies將派生自所有模板參數。 VirtualRoot的派生類從基類隱藏成員時,派生類的成員VirtualRoot於基類的成員,並且將被使用,即使繼承樹中的其他路徑可以到達基類成員。

請注意,您不需要為虛擬繼承付費,因為您從不創建use_policies類型的對象。 您只使用虛擬繼承來使用優勢規則。

template<typename B, int>
struct Inherit : B { };

template<class Pol1, class Pol2>
struct use_policies : Inherit<Pol1, 1>, Inherit<Pol2, 2>
{ };

因為我們可能不止一次從同一個類派生,所以我們使用類模板Inherit :禁止直接繼承同一個類兩次。 但允許間接繼承它。 您現在可以使用以下所有內容:

MyClass<int, float> m;
MyClass<float, double, ValueCompareIs< less<double> > > m;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM