Порядок аргументов шаблона Variadic, должен ли он всегда быть самым большим аргументом?

Я хотел бы изменить существующий конструктор классов:

template< typename T, typename... Ts >
MyClass( std::vector<T>& head, Ts& ...tail );

Чтобы можно было указать флаг обработки:

template< typename T, typename... Ts >
MyClass( MyEnum myEnum, std::vector<T>& head, Ts& ...tail );

Это прекрасно работает, однако мне было интересно, есть ли способ указать его как самый правый аргумент и, возможно, со значением по умолчанию. Я никогда не видел таких вариационных шаблонов, как это, но опять же, я не могу найти ничего явно, заявляя, что их не может быть. Я пробовал:

template< typename T, typename... Ts >
MyClass( std::vector<T>& head, Ts& ...tail, MyEnum myEnum );

...

MyClass myClass( dataA, dataB, dataC, MyEnum::VALUE );

Но компилятор ему не нравится, я предполагаю, что это связано с тем, как изменяются вариативные шаблоны и что они должны быть самым правым параметром?

Возможно ли это в С++ 11?

Ответы

Ответ 1

Нельзя иметь пакет функций в середине, но вы сталкиваетесь с гигантским препятствием при попытке сделать это с помощью конструктора: пакет параметров функции, который не встречается в конце описания параметра - list - это не выводимый контекст (§14.8.2.5 [temp.deduct.type]/p5, последняя маркерная точка), и шаблоны конструктора должны вызываться с использованием вычитания аргумента шаблона - вы не можете явно указать свои параметры шаблона.

То есть, чтобы иметь пакет параметров функции в середине, вы должны явно указать параметры шаблона при вызове функции:

template< typename T, typename... Ts >
void test( const std::vector<T>& head, const Ts& ...tail, MyEnum myEnum ) { }

test<double, int>(std::vector<double>(), 10, MyEnum()); // legal

Но это не скомпилируется:

test(std::vector<double>(), 10, MyEnum()); // No deduction performed for the parameter pack

Однако на языке нет способа явно указать параметры шаблона шаблона конструктора при его вызове (§14.8.1 [temp.arg.explicit]/p7):

[Примечание. Поскольку список аргументов явного шаблона следует за имя шаблона функции, а также функция-член преобразования шаблоны и шаблоны функций-членов конструктора вызываются без используя имя функции, нет способа предоставить явный шаблон список аргументов для этих шаблонов функций. -end note]

Таким образом, для конструкторов вы должны полагаться на вывод аргумента шаблона - который не работает, если ваш пакет параметров функции не находится в конце.

Ответ 2

Вы можете "обернуть" переменную в std::tuple:

template< typename T, typename... Ts >
MyClass( std::vector<T>& head, std::tuple<Ts& ...> tail, MyEnum myEnum );

...

MyClass myClass( dataA, std::tie( dataB, dataC ), MyEnum::VALUE );
// NOTE:                ^^^^^^^^^              ^

Живой пример (rev 2)