Подтвердить что ты не робот

Шаблон параметров по умолчанию vs variadic template: каков последний параметр шаблона?

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

template<typename T, class T2 = double, unsigned int... TDIM> myFunction(/* SOMETHING */)

или

template<typename T, unsigned int... TDIM, class T2 = double> myFunction(/* SOMETHING */)
4b9b3361

Ответ 1

На самом деле, пакеты параметров шаблона и параметры по умолчанию не должны быть последними в функции, если что-то, что приходит после него, будет выведено (или по умолчанию):

template<class T, class... Args, class T2 = int, class T3>
void f(T3){}

Обратите внимание, что вы никогда не можете указать что-либо для T2, так как все будет проглочено вариационным пакетом. Исходя из этого, я бы сказал, что имеет смысл ставить вариативные пакеты после параметров по умолчанию, если они должны быть указаны вручную. Для выведенных пакетов это больше стилистический выбор, и я лично ставил их последним.

Обратите внимание, что если они выведены как часть другого шаблона, вы можете даже иметь несколько вариационных пакетов:

template<class...> struct pack{};

template<class T, class... P1, class... P2, class T2>
void f(pack<P1...>, pack<P2...>, T2){}

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

Для шаблонов (первичных) классов это, разумеется, отличается, поскольку не может быть выведенных аргументов. На самом деле, переменные пакеты должны быть в конце списка параметров шаблона:

template<class T, class... Args, class T2=int>
struct X{}; // error

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

template<class T1, class T2>
struct X{};

template<template<class...> class T1, class... A1,
    template<class...> class T2, class... A2>
struct X<T1<A1...>, T2<A2...>>{};