可变参数模板参数上的C++11初始值设定项列表:为什么这不起作用
C++11 initializer lists on variadic template's parameters: why isn't this working
将可变模板的参数封装在初始值设定项列表中可以确保它们按顺序求值,但在这里不会发生:
#include <iostream>
using namespace std;
template<class T> void some_function(T var)
{
cout << var << endl;
}
struct expand_aux {
template<typename... Args> expand_aux(Args&&...) { }
};
template<typename... Args> inline void expand(Args&&... args)
{
bool b[] = {(some_function(std::forward<Args>(args)),true)...}; // This output is 42, "true", false and is correct
cout << "other output" << endl;
expand_aux temp3 { (some_function(std::forward<Args>(args)),true)... }; // This output isn't correct, it is false, "true", 42
}
int main()
{
expand(42, "true", false);
return 0;
}
为什么?
这似乎是一个错误。输出应该是您所期望的。
虽然不能保证构造函数调用的参数的求值顺序,但通常,可以保证支撑初始值设定项列表中表达式的求值顺序。
根据C++11标准第8.5.4/4段:
在支撑的初始化列表的初始化器列表中,初始化器子句,包括来自pack的任何结果展开式(14.5.3(按它们出现的顺序进行评估。也就是说,每个值的计算和与给定初始值设定项子句相关的副作用在每次值计算和副作用之前进行排序在初始值设定项列表的逗号分隔列表中,与其后的任何初始值设定项子句关联的效果。[注意:无论初始化的语义如何,此求值顺序都适用;例如,它适用于当初始值设定项列表的元素被解释为构造函数调用的参数时,即使通常,调用的参数没有顺序约束--尾注]
如前所述,您的问题是编译器错误。编写的代码应该按顺序评估其参数。
我的建议是明确你想做什么,以及按照什么顺序做,避免滥用逗号运算符(顺便说一句,如果some_function
返回了一个重写operator,
的类型,你的代码可能会表现得很奇怪(或使用初始值设定项列表保证(虽然是标准的,但也相对模糊(。
我的首选解决方案是编写并使用do_in_order
:
// do nothing in order means do nothing:
void do_in_order() {}
// do the first passed in nullary object, then the rest, in order:
template<typename F0, typename... Fs>
void do_in_order(F0&& f0, Fs&&... fs) {
std::forward<F0>(f0)();
do_in_order( std::forward<Fs>(fs)... );
}
你这样使用:
do_in_order( [&]{ some_function(std::forward<Args>(args)); }... );
将要执行的操作封装在一个匿名的null完全捕获lambda中,然后使用...
创建所述lambda的一整套实例,并传递给do_in_order
,后者通过完美转发按顺序调用它们。
对于编译器来说,这应该很容易内联并简化为一系列调用。它直接说明了它所做的事情,不需要奇怪的空类型转换、逗号运算符的使用或值被丢弃的数组。
- 概念中的cv限定符需要表达式参数列表
- 在没有参数列表的情况下使用模板名称"Event"无效,模板问题
- 错误 没有与参数列表匹配的重载函数"getline"实例
- std::vector 没有重载函数的实例与参数列表匹配
- 模板参数列表中的 false 在模板初始化期间计算为什么?
- C++模板/别名 - 模板参数列表中参数 1 处的类型/值不匹配
- 构造函数/函数声明参数列表中的统一初始化
- 模板化检查是否存在带有参数列表的类成员函数?
- 如何将类成员方法的参数列表自动填充写入可变参数?
- 带有整数的变量参数列表
- 转发变量参数列表以模拟 std::thread
- 错误:"模板<类_Tp,类_Dp>类 std::unique_ptr"的模板参数列表中参数 1 的类型/值不匹配
- C++-将具有引用的长参数列表重构为结构
- 缺少别名模板C++参数列表
- C++如果两个模板函数都与参数列表匹配,将调用哪个模板
- "extern"声明以及带有和不带参数列表的类模板实例的后续定义
- 使用显式模板参数列表和 [temp.arg.explicit]/3 的函数调用的演绎失败
- 没有函数模板的实例与我不知道为什么的参数列表匹配
- 我可以使用宏自动构建参数列表吗?
- 类成员函数参数列表是否可以依赖于模板参数?