Каковы правила использования `void` для специализации шаблона? - PullRequest
0 голосов
/ 08 января 2019

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

#include <array>

template <typename T> using Foo = std::array<T,123>;

const int FOO_SIZE = std::tuple_size<Foo<void>>::value;

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

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

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

Ответы [ 2 ]

0 голосов
/ 08 января 2019

На первый взгляд кажется удивительным, что это компилируется вообще, поскольку массив типа void явно исключен стандартом (11.3.4: 2 в связанном рабочем проекте N4659):

Массив может быть построен из одного из основных типов (кроме void), из указателя, из указателя на член, из класса, из тип перечисления или из другого массива.

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

Однако в C ++ есть щедрые правила, касающиеся ошибок при создании экземпляра шаблона, которые не требуются напрямую при компиляции фактического использования. В этом случае я считаю, что код работает - и переносим - поскольку вычисление std::tuple_size<Foo<void>>::value на самом деле не является экземпляром Foo<void>, но я бы рассматривал такое использование как perverse и что-то, чем вы, вероятно, должны быть избегать, поскольку Foo<void> не имеет юридической силы вне таких исключений.

0 голосов
/ 08 января 2019

Я не могу найти действительно убедительный конкретный набор стандартных формулировок, не воспроизведя половину стандарта (: D), но я считаю, что это четко определено.

Конструктор array требует, чтобы T было MoveConstructible или MoveAssignable , и вы не сможете создать экземпляр std::array<void, N>.

Но это нормально, потому что std::tuple_size этого делать не нужно, и не обязательно, чтобы это делалось, и ни одно из них не предъявляет никаких других особых требований, которые могут сделать ваш код проблематичным.

Однако это не похоже на полезный код, и не существует общего правила, когда void можно использовать в качестве аргумента шаблона. Вы должны посмотреть на требования к конкретной вещи, которую вы используете, в том контексте, в котором вы ее используете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...