我想将以下代码反向移植到 C++11:
template<unsigned i>
static void bar() { /* some code with compile-time optimizations for each value i */ }
template <unsigned... I>
void f()
{
((bar<I>()),...);
}
对参数包 I 的每个值调用“bar”的顺序很重要——我相信这在上面的 C++17 实现中有效,因为折叠表达式使用逗号运算符。
我最初选择了一个明确的递归实现:
template <unsigned... I>
typename std::enable_if<sizeof...(I) == 0>::type g() {}
template <unsigned head, unsigned... I>
void g()
{
bar<head>();
g<I...>();
}
这似乎可行,但需要 g() 的两个实现。在尝试使用单个函数时,我读到包扩展将在 make_tuple 中发生,并认为这会起作用:
template<unsigned... I>
static void h1()
{
std::make_tuple( (bar<I>(), 0)... );
}
不幸的是,这不会为执行顺序提供任何保证——事实上,对于 gcc,执行顺序正好相反。或者,我可以使用一个花括号初始化列表:
template<unsigned... I>
static void h2()
{
using expand = int[];
expand{ 0, ( bar<I>(), 0) ... };
}
这似乎保留了 gcc 的顺序,但我无法弄清楚这是否只是巧合。
所以,具体的问题是:
- h2的执行会保证正确的执行顺序吗?
- 有没有我错过的替代实现?