Можно получить первый элемент пакета параметров, как этот
template <typename... Elements>
struct type_list
{
};
template <typename TypeList>
struct type_list_first_element
{
};
template <typename FirstElement, typename... OtherElements>
struct type_list_first_element<type_list<FirstElement, OtherElements...>>
{
typedef FirstElement type;
};
int main()
{
typedef type_list<int, float, char> list;
typedef type_list_first_element<list>::type element;
return 0;
}
но не возможно подобным образом получить прошлой элемент как этот
template <typename... Elements>
struct type_list
{
};
template <typename TypeList>
struct type_list_last_element
{
};
template <typename LastElement, typename... OtherElements>
struct type_list_last_element<type_list<OtherElements..., LastElement>>
{
typedef LastElement type;
};
int main()
{
typedef type_list<int, float, char> list;
typedef type_list_last_element<list>::type element;
return 0;
}
с gcc 4.7.1 жалуется:
ошибка: ‘type’ in ‘struct type_list_last_element<type_list<int, float, char>>не называет тип
Какие параграфы из стандарта описывают это поведение?
Мне кажется, что пакеты параметров шаблона жадный в том смысле, что они потребляют все совпадающие аргументы, что в данном случае означает, что OtherElements
потребляет все три аргумента (int
, float
а также char
) а то уже ничего не осталось LastElement
поэтому компиляция не удалась. Я прав в предположении?
РЕДАКТИРОВАТЬ:
Чтобы уточнить: я не спрашиваю, как извлечь последний элемент из пакета параметров, я знаю, как это сделать. То, что я действительно хочу, это выбрать пакет отдельно от задней части, а не спереди, и, таким образом, повторение всей задней части для каждого элемента будет неэффективным. Предварительное изменение последовательности — самый разумный выбор.
Соответствующим пунктом является маркер в конце 14.5.5: 8:
14.5.5 Частичные специализации шаблона класса [temp.class.spec]
8 — В списке аргументов частичной специализации шаблона класса применяются следующие ограничения:
[…]
- Аргумент не должен содержать пакет расширенных параметров. Если аргумент является расширением пакета (14.5.3), он должен быть последним аргументом в списке аргументов шаблона.
Наблюдение:
<first,...>
такой же, как последний элемент <...>
...
не пусто <elem>
является elem
Так что вы должны сделать это рекурсивно, с помощью шаблона tail:
Рекурсия:
template <typename TypeList>
struct type_list_last_element;
template <typename FirstElement, typename... OtherElements>
struct type_list_last_element<type_list<FirstElement, OtherElements...>>
{
typedef typename type_list_last_element<type_list<OtherElements...>>::type type;
};
Хвост:
template <typename LastElement>
struct type_list_last_element<type_list<LastElement>>
{
typedef LastElement type;
};
[ОБНОВИТЬ] И использование:
int main()
{
typedef type_list<int, float, char> list;
typedef type_list_last_element<list>::type last;
return 0;
}
[КОНЕЦ ОБНОВЛЕНИЯ]
Увидеть ideone