ltj*_*jax 5 c++ variadic-templates c++11
我在一个开源项目中找到了基本上如下所示的代码:
template< typename... Args >
void expand_calls_hack(Args&&... args)
{}
template <unsigned int... Indices>
struct foo
{
static void bar(some_tuple_type& t)
{
meta::expand_calls_hack((std::get<Indices>(t).doSomething(), 0)...);
}
};
Run Code Online (Sandbox Code Playgroud)
我认为这个“构造”用于调用doSomething()每个元组元素。但是,在我看来,调用的顺序doSomething()是未定义的,至少在 C++03 中使用普通函数是这样。这将是一个错误,因为调用有副作用。我对此有两个问题:
(tupleElement.doSomething(), 0) 的用途是什么 - 那是逗号运算符吗?我认为这与使用 expand_calls_hack 扩展调用有关。
如何解决这个问题,以便从左到右评估调用?请注意,我需要在 VC2013 上编译。我试过扩展一个 lambda 列表并按顺序调用它,但我无法编译它。
我希望我没有遗漏太多的上下文,但出于好奇,这段代码的来源在 github 上,第 419 行
问题的第一部分非常简单:std::get<I>(t).doSomething()may return void。因此,您不能直接使用此表达式作为 的参数expand_calls_hack()。使用逗号运算符可以安排参数出现,即使doSomething()return也是如此void。
调用可变参数函数模板时函数求值的顺序并不特殊,即求值顺序是未定义的。然而,事实证明,使用大括号初始化时构造函数参数的评估顺序是定义的(例如,参见这个问题)。也就是说,您可以使用如下方式保证评估顺序:
namespace meta {
struct order {
template <typename... T>
order(T&&...) {}
};
}
// ...
template <unsigned int... Indices>
struct foo
{
template <typename T>
static void bar(T&& t)
{
meta::expand_calls_hack((std::get<Indices>(t).doSomething(), 0)...);
meta::order{(std::get<Indices>(t).doSomething(), 0)...};
}
};
Run Code Online (Sandbox Code Playgroud)
在上面的函数中,使用 会expand_calls_hack()在我的系统上从后到前评估表达式,而使用 则按order需要从前到后评估它们。我认为使用 可以实现类似的效果,std::initializer_list<int>这将具有不需要可变参数模板的效果:int无论如何,参数都是 s :
namespace meta {
struct init_order {
init_order(std::initializer_list<int>) {}
};
}
Run Code Online (Sandbox Code Playgroud)
它的使用方式与 完全相同meta::order。
| 归档时间: |
|
| 查看次数: |
877 次 |
| 最近记录: |