Потребление аргументов пакета параметров

Можно получить первый элемент пакета параметров, как этот

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 поэтому компиляция не удалась. Я прав в предположении?

РЕДАКТИРОВАТЬ:

Чтобы уточнить: я не спрашиваю, как извлечь последний элемент из пакета параметров, я знаю, как это сделать. То, что я действительно хочу, это выбрать пакет отдельно от задней части, а не спереди, и, таким образом, повторение всей задней части для каждого элемента будет неэффективным. Предварительное изменение последовательности — самый разумный выбор.

5

Решение

Соответствующим пунктом является маркер в конце 14.5.5: 8:

14.5.5 Частичные специализации шаблона класса [temp.class.spec]

8 — В списке аргументов частичной специализации шаблона класса применяются следующие ограничения:
[…]

  • Аргумент не должен содержать пакет расширенных параметров. Если аргумент является расширением пакета (14.5.3), он должен быть последним аргументом в списке аргументов шаблона.
4

Другие решения

Наблюдение:

  1. Последний элемент <first,...> такой же, как последний элемент <...>
    если только ... не пусто
  2. Последний элемент списка из одного элемента <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

1

По вопросам рекламы [email protected]