我想在参数包扩展期间为每个参数增加一个计数器。 这是我想要实现的一些伪代码:
template<class ... Args>
void doSomething(Args ... _args)
{
std::size_t counter = 0;
bar(doSomethingWithOneArg(_args, counter++)...);
}
此代码的问题在于,虽然保留了Args
的顺序,但未定义评估函数参数的顺序,即在clang
上计数器的顺序表达式的评估与Args
的顺序相同,而gcc
中的表达式则相反。实现这一目标的便携式标准方法是什么?
谢谢!
答案 0 :(得分:4)
您可以添加辅助功能:
<svg>
<path fill="#FFFFFF" stroke="#000000" stroke-miterlimit="10" d="M21,34.328C21,15.693,32.477,0.515,50.124,0.515
C67.77,0.515,79,16.928,79,34.328c0,17.399-29,65.157-29,65.157S21,52.962,21,34.328z"/>
</svg>
答案 1 :(得分:1)
如果您希望评估顺序与doSomething
的参数顺序一致,您可以将参数扩展为初始值设定项:
template <typename ...Args, std::size_t ...N>
void doSomethingImpl(std::index_sequence<N...>,
std::tuple<Args...> && args)
{
using std::get;
int t_[] = { 0, (static_cast<void>(oneCommand(
get<N>(std::forward<decltype(args)>(args)), N)), 0)... };
static_cast<void>(t_); // "use" t_ to silence warnings
}
template <typename ...Args>
void doSomething(Args &&... args)
{
doSomethingImpl(std::make_index_sequence<sizeof...(Args)>(),
std::forward_as_tuple(std::forward<Args>(args)...));
}
答案 2 :(得分:1)
您可以将list-initializatio与逗号运算符结合使用来对函数调用进行排序:
template<class T>
void doSomethingWithOneArg(const T&, std::size_t counter)
{
std::cout << counter << ": " << typeid(T).name() << '\n';
}
template<class ... Args>
void doSomething(Args ... args)
{
std::size_t counter = 0;
std::initializer_list<int>{ ( doSomethingWithOneArg(args, counter++), 0) ... };
}
int main() {
doSomething(char(0), int(0), long(0));
}
8.5.4列表初始化(N4296)
4 在braced-init-list的initializer-list中, initializer-clause,包括包扩展产生的任何条款 (14.5.3),按照它们出现的顺序进行评估。那是, 与给定相关的每个值计算和副作用 initializer-clause在每个值计算之前排序 与其后面的任何初始化子句相关联的副作用 逗号分隔的初始化列表列表。