【发布时间】:2020-04-22 17:13:00
【问题描述】:
最近我在学习 C++ 和可变参数模板。我尝试编写一个模板函数,它接受一个容器(我对其进行了简化,并且在这个问题中我只使用list)和一些其他参数,并将其他参数放置到容器中。我的代码如下所示:
#include <iostream>
#include <list>
#include <utility>
template <typename Container, typename... Args>
void my_emplace(Container &c, Args &&... args){
c.emplace_back(std::forward<Args>(args)...);
}
int main(void) {
std::list<int> l = {1, 2};
my_emplace(l, 3, 4, 5);
for (auto i : l)
std::cout << i << ", ";
return 0;
}
但是,代码不起作用:
$ g++ -std=c++17 test.cpp
...
/usr/include/c++/7/ext/new_allocator.h:136:4: error: new initializer expression list treated as compound expression [-fpermissive]
{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
我在互联网上找到了解决方案 -- c.emplace_back(std::forward<Args>(args)...); 被(c.emplace_back(std::forward<Args>(args)), ...); 替换。该代码与它完美配合。
这是我不明白的部分。我从未见过这种语法。
- 为什么我的代码不起作用? This answer here 基本上说是正确的。
- 我找到的正确解决方案实际上有什么作用?我从未使用过逗号运算符,但我发现在使用时,两个表达式都被计算并且第一个表达式的结果被丢弃。它在这里做什么?为什么没有它代码就不能工作?
感谢您的回答。
【问题讨论】:
-
你用 3 个参数调用 emplace_back,但 'int constructor' 只需要 1 个
-
好问题。附注:使用
vector作为您的默认容器(除非您有充分的理由选择list),并且不要使用字母l作为标识符,因为很难看出区别1. -
*通常不要使用单字母标识符,除非它们已经很好地建立起来,例如轴的“x、y、z”。
-
@xtofl @Yamahari :代码本身看起来不像这样,我缩短了它以简化我的问题。在函数体中,我还尝试使用多个容器,如vector(
emplace_back)、set(emplace)等,并使my_emplace“通用”。 -
太棒了!最好也朝着这些良好实践的方向进行简化:)。它可以减少挑剔的读者的注意力,并为您提供更好的答案。
标签: c++ templates variadic-templates perfect-forwarding comma-operator