我写了以下的sumhelper:
template <typename T1, typename T2>
auto sum(const T1& v1, const T2& v2) -> decltype( v1 + v2) {
return v1 + v2;
}
template <typename T1, typename T2, typename... Ts>
auto sum(const T1& v1, const T2& v2, const Ts&... rest) -> decltype( v1 + v2 + sum(rest...) ) {
return v1 + v2 + sum(rest... );
}
这是CPP文件
#include <iostream>
#include <type_traits>
#include "Sum.hpp"
struct A {
int x;
A(const int a) : x(a) { std::cout<<x<<std::endl; };
A &operator+(const A &tmp) const {
std::cout<<" + "<<tmp.x<<") ";
};
};
int main () {
std::cout<<"sum of 1,2,3,4 is : ";
auto ans = sum(1,2.2,3,4);
A a(1);
A b(2);
A c(3);
std::cout<<a.x;
a+b+c;
sum(a,b,c); //Here is syntax error
std::cout<<ans<<std::endl;
return 0;
}
为什么我无法做总和(a,b,c)?当我有一个+ b + c作为演示工作。
当我传递对象时,它会产生编译错误,但在传递基本类型
时则不会我无法理解错误模板参数演绎/替换失败..怎么办?
答案 0 :(得分:2)
这是我的不好(从上一个回答)你应该在顶部为单个元素添加一个模板专门化。否则sum(1,2,3)
将找不到匹配项,因为前两个参数将由可变参数匹配,另一个参数需要两个参数。只剩一个了。
template <typename T>
T sum(const T& v) {
return v;
}
这又是另一个问题,你的操作员+流出而没有返回任何东西。这是未定义的行为。如果你把它定义为一个成员,它应该是const。
struct A {
int x;
A(const int a) : x(a) { std::cout<<x<<std::endl; };
A operator+(const A &a1) const
{
return A(a1.x + x);
}
};
所以你的完整程序现在应该是这样的
template <typename T>
T sum(const T& v) {
return v;
}
template <typename T1, typename T2>
auto sum(const T1& v1, const T2& v2) -> decltype( v1 + v2) {
return v1 + v2;
}
template <typename T1, typename T2, typename... Ts>
auto sum(const T1& v1, const T2& v2, const Ts&... rest) -> decltype( v1 + v2 + sum(rest...) ) {
return v1 + v2 + sum(rest... );
}
struct A {
int x;
A(const int a) : x(a) { };
A operator+(const A &a1) const { return A(a1.x + x); }
};
int main () {
std::cout<<"sum of 1,2.2,3,4 is : ";
auto ans = sum(1,2.2,3,4);
cout << ans;
A a(1); A b(2); A c(3);
a+b+c;
auto ans2 = sum(a,b,c);
std::cout<<std::endl<<"sum of A(1),A(2),A(3) is : ";
std::cout<<ans2.x<<std::endl;
return 0;
}
标准输出
sum of 1,2.2,3,4 is : 10.2
sum of A(1),A(2),A(3) is : 6
答案 1 :(得分:2)
以下是变量apply_binop
的变体,它将任意操作作为第一个参数,以及将sum
包装器传递给它的二进制add
。 apply_binop
更好(更明确地)称为foldr
我相信:
#include <utility>
#include <iostream>
#define RETURNS(x) ->decltype(x) { return (x); }
struct add {
template<typename T, typename U>
auto operator()( T&& t, U&& u ) const
RETURNS( std::forward<T>(t)+std::forward<U>(u) )
};
template<typename Op, typename T0>
auto apply_binop( Op&& op, T0&& t0 )
RETURNS(std::forward<T0>(t0))
template<typename Op, typename T0, typename T1, typename... Ts>
auto apply_binop( Op&& op, T0&& t0, T1&& t1, Ts&&... ts )
RETURNS(
op(
std::forward<T0>(t0),
apply_binop(op, std::forward<T1>(t1), std::forward<Ts>(ts)...)
)
)
template<typename... Ts>
auto sum( Ts&&... ts )
RETURNS( apply_binop( add(), std::forward<Ts>(ts)... ) )
int main() {
std::cout << sum(1,2,3,4,5) << "\n";
std::cout << sum(1) << "\n";
std::cout << sum(1,2) << "\n";
std::cout << sum(1,2,3) << "\n";
std::cout << sum(1,2,3,4) << "\n";
std::cout << sum(1,2,3,4.7723) << "\n";
}
它是foldr
,因为它将二进制操作应用于最右边的两个,然后获取该结果并将其应用于最后一个,等等。foldl
从左侧开始执行相同操作。
宏RETURNS
弥补了C ++无法推断单行函数的返回类型(我相信这将在C ++ 17中修复)。让gcc 4.7.2接受上面只有两个apply_binop
覆盖,需要进行一些调整。
在没有3次或更多次覆盖的情况下实施foldl
有点棘手。
以下是另一个答案,他们讨论了解决此问题的更好方法:
答案 2 :(得分:1)
这是一个正确的可变总和
#include <iostream>
namespace cs540 {
template <typename T>
const T & sum(const T & v) {
return v;
}
template <typename T, typename T2, typename ... Ts>
T sum(const T & v, const T2 & w, const Ts & ... params) {
return sum(w+v,params...);
}
}
int main() {
using namespace cs540;
using namespace std;
cout << sum(1.1,2,3,4,6,8,9,1.1) << endl;
}
您还需要将方法操作符+标记为const