Пакет параметров должен быть в конце списка параметров... когда и почему?



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



Другими словами, этот компилирует:



class C {
template<typename T, typename... Args, typename S>
void fn() { }
};


Следующий не делает:



template<typename T, typename... Args, typename S>
class C { };


Почему первый случай считается правильным, а второй-нет?

Я имею в виду, если это юридический синтаксис, разве не должно быть так в обоих случаях?

Быть ясно, что реальная проблема заключается в том, что я определял класс, подобный следующему:



template<typename T, typename... Args, typename Allocator>
class C { };


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

Тем не менее, я получил ошибку:




Пакет параметров 'Args' должен находиться в конце списка параметров шаблона




Итак, мне просто было любопытно полностью понять, почему это принимается в одних случаях, но не принимается в других.



Вот похожий вопрос, но он просто объясняет, как решить проблему, и это было мне совершенно ясно.

733   2  

2 ответов:

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

template<typename T, typename... Args, typename S> void fn() { }
int main() { fn<int, int, int>(); }
test.cpp: In function 'int main()':
test.cpp:2:32: error: no matching function for call to 'fn()'
 int main() { fn<int, int, int>(); }
                                ^
test.cpp:1:57: note: candidate: template<class T, class ... Args, class S> void fn()
 template<typename T, typename... Args, typename S> void fn() { }
                                                         ^
test.cpp:1:57: note:   template argument deduction/substitution failed:
test.cpp:2:32: note:   couldn't deduce template parameter 'S'
 int main() { fn<int, int, int>(); }
Компилятор не может определить, какие параметры шаблона принадлежат пакету параметров, а какие-пакету S. На самом деле, как указывает @T. C., Это должно быть синтаксической ошибкой, потому что шаблон функции, определенный таким образом, никогда не может быть создать экземпляр.

Более полезным шаблоном функции было бы что-то вроде

template<typename T, typename... Args, typename S> void fn(S s) { }

Поскольку теперь компилятор может однозначно сопоставить параметр функции s с типом шаблона S, с побочным эффектом, что S будет всегда выводиться - все явные параметры шаблона после первого будут принадлежать Args.

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

Из черновика n4567

Http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4567.pdf

[темп.param] / 11

[...]Если шаблон - параметр шаблона или псевдонима первичного класса шаблон-это набор параметров шаблона, он должен быть последним шаблон-параметр .[...]

(если бы они были выведены, это было бы неоднозначно, как в Примере шаблона функции).

Первый из них не прав. Компилятор просто глючит и не смог его диагностировать. [темп.парам]/11:

Пакет параметров шаблона шаблона функции не должен следовать другим параметром шаблона, если этот параметр шаблона не может быть выводится из parameter-type-list шаблона функции или имеет аргумент по умолчанию (14.8.2).


Если тип функции T(Args...) имеет значение для конечного пользователя, один из способов исправить это будет вместо этого следует использовать частичную специализацию:

template<class F, class Alloc> class C; //undefined
template<class T, class... Args, class Alloc>
class C<T(Args...), Alloc> {
    // implementation
};

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

Comments

    Ничего не найдено.