Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I have my templated container class that looks like this:

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

Which means that when I instantiate an object of this class, I can do it several different ways:

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

Those are all good. The problem comes when I want to instantiate a MyClass that uses a non-default version of the ValueCompareFunctor argument, but I still want to use the default value of the KeyCompareFunctor argument. Then I have to write this:

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

It would be much more convenient if I could somehow omit the third argument and just write this:

MyClass<KeyType, ValueType, MyCustomValueCompareFunctor> myObject;

Since the MyCustomValueCompareFunctor works only on objects of type MyValueType and not on objects of type MyKeyType, it seems like the compiler could at least theoretically work out what I meant here.

Is there a way to do this in C++?

like image 238
Jeremy Friesner Avatar asked Aug 01 '09 04:08

Jeremy Friesner


2 Answers

In general, both in templates and functions or methods, C++ lets you use default for (and thereby omit) only trailing parameters -- no way out.

I recommend a template or macro to shorten AnObnoxiouslyLongSequenceOfCharacters<MyKeyType> to Foo<MyKeyType> -- not perfect, but better than nothing.

like image 111
Alex Martelli Avatar answered Oct 08 '22 12:10

Alex Martelli


No. The closest you can come is to allow users to specify some sentinel type - like void - meaning "use default value here", and use template metamagic inside your class to typedef the real default if void was given to you. But this probably isn't a good idea from readability point of view.

like image 43
Pavel Minaev Avatar answered Oct 08 '22 10:10

Pavel Minaev