如何将可变参数模板展开为initializer_list并获取begin/end迭代器
问题与解决方案
问题背景
现有两个vector:
std::vector<int> v1{ 1, 2, 3 }; std::vector<int> v2{ 4, 5, 6 };
需要创建一个std::initializer_list<std::vector<int>::iterator>,包含两个vector的begin和end迭代器,即最终列表需包含4个元素:v1.begin(), v1.end(), v2.begin(), v2.end()。
当前实现的可变参数模板函数因逗号运算符的特性,仅生成了2个迭代器(仅保留了每个vector的end迭代器),代码如下:
template<class... Ts> void foo(Ts... args) { std::initializer_list<std::vector<int>::iterator> il{ (std::begin(args), std::end(args))... }; } int main() { std::vector<int> v1{ 1, 2, 3 }; std::vector<int> v2{ 4, 5, 6 }; foo(v1, v2); }
原因分析
代码中的(std::begin(args), std::end(args))是逗号表达式,C++中逗号运算符会先执行左操作数,然后丢弃其结果,返回右操作数的值。因此每个参数仅会向初始化列表中添加std::end(args)的结果,最终列表只有2个元素,不符合需求。
修复方案
调整参数包的展开方式,让每个参数同时生成begin和end两个迭代器:
template<class... Ts> void foo(Ts... args) { std::initializer_list<std::vector<int>::iterator> il{ std::begin(args), std::end(args)... }; }
展开逻辑说明
这里的参数包展开会将每个args元素依次展开为std::begin(args)和std::end(args),最终初始化列表的内容等价于:
{std::begin(v1), std::end(v1), std::begin(v2), std::end(v2)}
完美生成包含4个目标迭代器的initializer_list。
内容的提问来源于stack exchange,提问作者Ragdoll Car
相关产品推荐
相关产品推荐

