Hol*_*olt 5 c++ templates temporary template-meta-programming c++14
我需要创建一个reduce类似的函数std::reduce,但不是处理容器,这个函数应该适用于可变参数.
这就是我目前拥有的:
template <typename F, typename T>
constexpr decltype(auto) reduce(F&&, T &&t) {
return std::forward<T>(t);
}
template <typename F, typename T1, typename T2, typename... Args>
constexpr decltype(auto) reduce(F&& f, T1&& t1, T2&& t2, Args&&... args) {
return reduce(
std::forward<F>(f),
std::forward<F>(f)(std::forward<T1>(t1), std::forward<T2>(t2)),
std::forward<Args>(args)...);
}
Run Code Online (Sandbox Code Playgroud)
以下按预期工作:
std::vector<int> vec;
decltype(auto) u = reduce([](auto &a, auto b) -> auto& {
std::copy(std::begin(b), std::end(b), std::back_inserter(a));
return a;
}, vec, std::set<int>{1, 2}, std::list<int>{3, 4}, std::vector<int>{5, 6});
assert(&vec == &u); // ok
assert(vec == std::vector<int>{1, 2, 3, 4, 5, 6}); // ok
Run Code Online (Sandbox Code Playgroud)
但以下不起作用:
auto u = reduce([](auto a, auto b) {
std::copy(std::begin(b), std::end(b), std::back_inserter(a));
return a;
}, std::vector<int>{}, std::set<int>{1, 2},
std::list<int>{3, 4}, std::vector<int>{5, 6});
Run Code Online (Sandbox Code Playgroud)
这基本上崩溃 - 为了使这项工作,我需要例如将第一个定义更改reduce为:
template <typename F, typename T>
constexpr auto reduce(F&&, T &&t) {
return t;
}
Run Code Online (Sandbox Code Playgroud)
但如果我这样做,第一个片段就不再起作用了.
问题在于转发参数和reduce函数的返回类型,但我可以找到它.
我应该如何修改我的reduce定义以使两个片段都有效?
你可以尝试
template <typename F, typename T>
constexpr T reduce(F&&, T &&t) {
return std::forward<T>(t);
}
Run Code Online (Sandbox Code Playgroud)
当第二个参数是右值时,这将返回纯右值,否则返回引用该参数的左值。你的片段似乎没问题。
或者,只需使用您的第二个变体并进行vec必要std::ref的修改即可。这也是模板按值处理对象时的标准方法。