我有我的模板的容器类,看起来是这样的:

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;

这些都是良好的。问题是当我想到的实例有MyClass使用非缺省版本的ValueCompareFunctor的论点,但我仍然想要使用默认值KeyCompareFunctor的论点。那么我要写这样的:

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

它将更多的方便,如果我可以以某种方式忽略的三个参数和只要写这样的:

MyClass<KeyType, ValueType, MyCustomValueCompareFunctor> myObject;

由于MyCustomValueCompareFunctor仅适用于类型的对象MyValueType和不对象的类型MyKeyType,它似乎是编译器可能至少在理论上工作出什么我的意思是在这里。

有没有办法做到这一点,在C++?

有帮助吗?

解决方案

通常,在模板和函数或方法中,C ++都允许您使用默认值(从而省略)尾随参数 - 没有出路。

我建议使用模板或宏来缩短AnObnoxiouslyLongSequenceOfCharacters<MyKeyType>Foo<MyKeyType> - 不完美,但总比没有好。

其他提示

没有。你最接近的是允许用户指定一些哨兵类型 - 比如void - 意思是<!>“;在这里使用默认值<!>”,并在你的班级中使用模板metamagic typedef真正的默认值如果<=>给了你。但从可读性的角度来看,这可能不是一个好主意。

提高参数提高形图的命名参数 是的努力命名参数对模板功能/方法。他们给的机会,提供论据无论在哪一个了你喜欢。一些参数可以是任选的,使用默认值。

同样的方法可以应用于模板的论点。而不是具有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的派生类隐藏了一个成员,那么派生类的成员优先于基类的成员,并且将被使用,即使基类成员可以通过其他路径到达继承树。

请注意,您不需要为虚拟继承付费,因为您从不创建类型为Inherit的对象。您只使用虚拟继承来使用优势规则。

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

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

因为我们可能不止一次从同一个类派生,所以我们使用类模板<=>:禁止直接继承同一个类两次。但允许间接继承它。您现在可以使用以下所有内容:

MyClass<int, float> m;
MyClass<float, double, ValueCompareIs< less<double> > > m;
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top