Variadic模板initilizer_list技巧

时间:2017-01-12 18:56:44

标签: c++ tuples variadic-templates c++17

我在visual studio 2017 RC上用C ++ 17编写了for_each_tuple,我对这个实现感到震惊。

退房:

template<class fun_t, class tuple_t>
constexpr auto for_each_tuple(fun_t& fun, tuple_t&& tuple) {

    std::apply([&](auto&&... args) {
        auto l = { (fun(std::forward<decltype(args)>(args)), 0)... };
    }, std::forward<tuple_t>(tuple));
}

int main() {
    auto tup = std::make_tuple(
        1, 2, 3, 4
    );
    for_each_tuple([](auto& arg) { ++arg; }, tup);
    for_each_tuple([](auto& arg) {std::cout << arg; }, tup);

}

输出: 2345

我对这部分有严肃的问题:

auto l = { (fun(std::forward<decltype(args)>(args)), 0)... };

这只是编译技巧还是完全标准的正确方法?

究竟函数调用如何解析为std :: initilizer_list?

如何让您的意见更好?

1 个答案:

答案 0 :(得分:3)

在C ++ 17中,这个:

auto l = { (fun(std::forward<decltype(args)>(args)), 0)... }; 

可以改写为:

(fun(std::forward<decltype(args)>(args)), ...);

在等待折叠表达式时,列表技巧是完全合法的(从标准的角度来看)C ++ 11 / C ++ 14解决方法。
基本思想是创建一个列表(或数组),以便在之后立即丢弃。由于逗号运算符的工作原理,该容器用零填充。最后,参数包的展开只会强制为每个参数调用给定的函数 换句话说,你可以想象它如下:

auto l = { (fun(std::forward<decltype(arg0)>(arg0)), 0), (fun(std::forward<decltype(arg1)>(arg1)), 0), (fun(std::forward<decltype(arg2)>(arg2)), 0), and so on... };