参数包参数消耗

Parameter pack argument consumption

本文关键字:参数 包参数      更新时间:2023-10-16

可以获得类似的参数包的第一个元素

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抱怨:

错误:"struct-type_list_last_element<type_list<int,float,char>gt;'没有命名类型

标准中的哪些段落描述了这种行为?

在我看来,模板参数包是贪婪的,因为它们消耗了所有匹配的参数,在这种情况下,这意味着OtherElements消耗了所有三个参数(intfloatchar),然后LastElement就什么都没有了,所以编译失败了。我的假设正确吗?

编辑:

澄清一下:我不是在问如何从参数包中提取最后一个元素,我知道如何做到这一点。我实际上想要的是把背包从后面挑选出来,而不是从前面挑选出来,因此,对于每个元素,一直重复到后面都是无效的。事先明显颠倒顺序是最明智的选择。

相关条款是14.5.5:8:末尾的项目符号

14.5.5类模板部分专业化〔temp.Class.spec〕

8-在类模板部分专业化的参数列表中,适用以下限制:[…]

  • 参数不应包含未扩展的参数包。如果参数是包扩展(14.5.3),则它应是模板参数列表中的最后一个参数

观察:

  1. <first,...>的最后元素与<...>的最后元素相同如果只有CCD_ 8不为空
  2. 一个元素列表<elem>的最后一个元素是elem

所以你必须递归地使用尾部模板:

递归:

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;
};

[UPDATE]和用法:

int main()
{
typedef type_list<int, float, char> list;
typedef type_list_last_element<list>::type last;
return 0;
}

[结束更新]

参见videone