我想写一个通用的sum函数,如下所示,但不是在模板语法中,而是在lambda语法中:
template<typename T>
auto Sum(T lastSummand)
{
return lastSummand;
}
template<typename T, typename... Ts>
auto Sum(T firstSummand, Ts... restSummands)
{
return firstSummand + Sum(restSummands...);
}
因为通用lambda映射到模板,所以应该可以执行以下操作:
auto sum = [](auto firstSummand, auto... restSummands) { ... };
但我无法弄清楚如何使用lambdas进行递归。在这个和其他地方搜索并没有带来多少。
答案 0 :(得分:4)
在C ++ 14中,你实际上并不需要通过普通lambda来进行递归 例如,您可以这样做:
#include<type_traits>
#include<iostream>
int main() {
auto l = [](auto... values) {
std::common_type_t<decltype(values)...> ret = {};
decltype(ret) _[] = { (ret += values)... };
(void)_;
return ret;
};
auto v = l(0, 0., 5, 4.2);
std::cout << v << std::endl;
}
返回类型由给定包的std::common_type_t
给出
其余代码包含在等待折叠表达式时常用的常用模式。
在C ++ 17中它将成为:
#include<iostream>
int main() {
auto l = [](auto... values) { return (values + ...); };
auto v = l(0, 0., 5, 4.2);
std::cout << v << std::endl;
}
在wandbox上查看。
如果您想在运行中验证给定参数是所有算术类型,您可以使用bool技巧,如下所示:
auto l = [](auto... values) {
static_assert(
std::is_same<
std::integer_sequence<bool, true, std::is_arithmetic<decltype(values)>::value...>,
std::integer_sequence<bool, std::is_arithmetic<decltype(values)>::value..., true>
>::value, "!"
);
std::common_type_t<decltype(values)...> ret = {};
decltype(ret) _[] = { (ret += values)... };
(void)_;
return ret;
};
答案 1 :(得分:0)
好吧,我假设您需要类似仿函数的类型来计算总和,如果您正在使用lambda。如果是这样,那么我想你可以写一个小的通用类来取代那个lambda。
template < typename T > struct Sum
{
template < typename U >
T operator () (U v) const noexcept
{
return static_cast< T >(v);
}
template < typename U, typename... Values >
T operator () (U v, Values&&... vs) const noexcept
{
return static_cast< T >(v) + (*this)(std::forward< Values >(vs)...);
}
};
用作:
auto sum = Sum< int >();
printf("%d\n", sum(23, 4.0, true, 7));
我以这样的方式编写它,可以提前指定返回类型。但我想你可以调整它以使其成为通用的。
如果这不是您的意图,请忽略此答案。