Вопрос по templates, c++, c++11 – Каков синтаксис выражения для поддержки типов C ++?
=====================================================================================

Я работал с шаблонным классом, который принимает набор целых чисел. Код был как,

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

В то время как в C ++ мы имеем большое количество операторов, и их можно использовать для формулирования экзотических шаблонов выражений (скажем,`boost::xpressive``boost::lambda``boost::spirit` и т. д.) возможностей для манипулирования типами гораздо меньше.

В выступлении Boostcon Шон Родитель отметил, что до сих пор не может написать`pair` обозначать`a pair of integers`, В моей персидской библиотеке я сделал такой синтаксис`tuple` обозначить кортеж из 3 целых чисел вместо записи кортежа с 3 int в аргументах типа, отмечая, что я нигде не записываю необработанный массив в качестве аргумента кортежа! (нота:`std::array` отличается от описанного выше, так как std :: array не может хранить ссылки, пока`tuple` можно сказать`std::tuple` возможно)

Итак, я хочу знать, что это за "выражения типа " Я могу написать?

До сих пор я могу думать о типе объекта, типе функции, ссылочном типе, с / без модификаторов cv, указателей и т. Д., Например

Но я верю, что возможно гораздо больше.

ПРИМЕЧАНИЕ: этот вопрос чисто теоретический,**Я просто хочу знать все виды синтаксиса, которые я могу написать внутри <> в качестве аргумента типа**и не о читабельности / морали, или даже о том, как я могу реализовать некоторые из приведенных мной примеров, например, рабочий класс.

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

Я придумал реализацию, которая делает`span` бытьпсевдоним шаблона за`indexes`, используя трюк типа вывода в`constexpr` функции:

Теперь вы можете съесть свой торт и съесть его:

Но, возможно, более интересно,**вы все еще можете иметь свой основной`work` шаблон сырой** список аргументов шаблона:

Смотрите полную рабочую демонстрацию здесь:[GCC на Ideone](http://ideone.com/U2geNF), Я скомпилировал это с Clang локально.

Полный кодКод для`expand_span` здесь дублируется на случай, если ссылка не работает:



ия - находится в.`[dcl.decl]`

В основе этого синтаксиса лежат шесть фундаментальных конструкций, внутри которых`T` может быть заменен любой из других конструкций в списке. [В следующих,`(T)` представляет список из нуля или более типов (которые могут заканчиваться на '...»), а также представляет список одного или нескольких типов.]

**РЕДАКТИРОВАТЬ**Тип специализации шаблона класса может быть заменен на любой:`T`

Существуют комбинации из вышеперечисленного, которые создают конструкции, которые имеют особое значение:

Кроме того, некоторые конструкции могут быть cv-квалифицированными:

Не все комбинации приводят к допустимым типам. В соответствии с`[basic.compound]`можно использовать только следующие комбинации:

Составные типы могут быть созданы следующими способами:

массивы объектов данного типафункции, которые имеют параметры заданных типов и возвращают void или ссылки или объекты заданного типауказатели на void или объекты или функции (включая статические члены классов) заданного типассылки на объекты или функции данного типауказатели на нестатические члены класса, которые идентифицируют члены данного типа в объектах данного классаДополнительные ограничения упоминаются:

`[dcl.ptr]` нет указателей на ссылки

`[dcl.ref]` Не должно быть ссылок на ссылки, массивов ссылок и указателей на ссылки.

`[dcl.mptr]` Указатель на член не должен указывать на ... член со ссылочным типом или "cv void. "

`[dcl.fct]` Список параметров (void) эквивалентен пустому списку параметров. За исключением этого особого случая, void не должен быть типом параметра. ... Если тип параметра включает в себя тип формы «указатель на массив неизвестных границ T » или же "ссылка на массив неизвестных границ T » программа плохо сформирована. Функции не должны иметь тип возвращаемого типа массива или функции.

Некоторые из возможных конструкций**не могу** использоваться в качестве аргументов шаблона. Когда вы явно указываете набор аргументов шаблона, компилятор должен проверить, что аргументы шаблона могут быть заменены параметрами шаблона, не приводя к 'неверный тип, В соответствии с`[temp.deduct]\2`следующие конструкции составляют недопустимые типы:

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

Попытка создать массив с типом элемента void, типом функции или ссылочным типом или попытка создать массив с нулевым или отрицательным размером.

Попытка использовать тип, который не является типом класса в определенном имени.

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

Попытка создать указатель на ссылочный тип.

Попытка создать ссылку на ссылочный тип или ссылку на void.

Попытка создать "указатель на член T " когда T не тип класса.

```
`template int f(int T::*);
int i = f(0);`
```
Попытка выполнить недопустимое преобразование либо в выражении аргумента шаблона, либо в выражении, используемом в объявлении функции.

```
`template int f(int);
int i2 = f(0); // can’t conv 1 to int*`
```
Попытка создать тип функции, в которой параметр имеет тип void.

Попытка создать cv-квалифицированный тип функции.**РЕДАКТИРОВАТЬ:** Это основано на C ++ 03, но также относится к C ++ 11 (который добавляет rvalue ссылочные типы)