[英]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.