可以获取参数包的 first 元素,如this
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;
}
但不可能像<{3}}那样获得 last 元素
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抱怨:
错误:'struct type_list_last_element&lt; type_list&lt; int,float,char&gt;&gt;'中的'type'没有命名类型
标准的哪些段落描述了这种行为?
在我看来,模板参数包是 greedy ,因为它们使用所有匹配的参数,在这种情况下意味着OtherElements
消耗所有三个参数({{1} },int
和float
)然后char
没有任何内容,因此编译失败。我在假设中是否正确?
修改
澄清:我不是问如何从参数包中提取最后一个元素,我知道如何做到这一点。我真正想要的是从背面而不是前面挑选背包,因此每个元素一直到后面的递归都是无效的。事先明确地逆转序列是最明智的选择。
答案 0 :(得分:4)
相关条款是14.5.5:8结尾处的子弹:
14.5.5类模板部分特化[temp.class.spec]
8 - 在类模板部分特化的参数列表中,以下限制适用: [...]
- 参数不应包含未展开的参数包。如果参数是包扩展(14.5.3),则它应该是模板参数列表中的最后一个参数。
答案 1 :(得分:1)
观察:
<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;
}
[END UPDATE]
请参阅ideone