我想知道是否有一种方法可以实现这一点,或者至少有一种更好的方法可以完全使用模板实现这一目标:
template <typename T, typename U>
double sum(const vector<T>& vt, const vector<U>& vu)
{
// . . .
double sum = 0;
for (int i = 0; i < size; ++i)
sum += convert(vt[i] * vu[i]);
return sum;
}
T
和U
应该是数字,比如double、int或任何其他支持这些操作的类(我不熟悉模板)。
有没有办法去掉这个convert()
函数(它获得特定类的数字成员),只写sum += vt[i] * vu[i]
?
如果为所有T
和U
定义了对double
的隐式转换运算符(或者一个为double
,另一个为可以升级为double
的类型),则vt[i]
和vu[i]
将转换为double
s,相乘的结果将为double
,正如您所希望的那样。
示例:
class Foo
{
double value;
public:
// ...
operator double() const { return value; }
};
但你必须决定返回什么。
我觉得你有点希望。
template <typename T, typename U, typename resultType = double >
resultType sum(const vector<T>& vt, const vector<U>& vu)
{
// . . .
resultType sum = 0;
for (size_t i = 0; i < vt.size(); ++i) {
// two versions of sum - coerced to resultType before and after
// multiplication
sum += static_cast<resultType>(vt[i]) * static_cast<resultType>(vu[i]);
sum += static_cast<resultType>(vt[i] * vu[i]);
}
return sum;
}
sum+=
的两个版本将产生不同的结果。若sum是一个整数,则可能发生截断。
在double和int之间的乘法中,类型提升发生在一个中,但在另一个中被规范化。
更新
带有resultType=doubleT和U是双的,那么结果是相同的。
T是整数,U是双。T被提升到两倍,结果是一样的。
T和U是整数。sum += static_cast<double>( vt[i] * vu[i] );
将整数相乘,可能溢出并返回不同的结果。
带有resultType=int
T和U是双的-结果要么是数字的整数截断,要么是结果的整数截断。
static_cast(5.3)*static_cast(3.7);=>15
static_cast(5.3*3.7);=>static_cast(19.61)=>19
T是整数,U是双。如上所述T和U是整数。两者都是一致的。
有一个类和一个
operator double() const { return value; }
正如其他文章中所建议的那样,那么第一个sum+=将起作用,其中第二个sum依赖于至少一个数字类型,因此编译器可以尝试显式double
转换。
对于两个class
,则sum += static_cast<resultType>(vt[i]) * static_cast<resultType>(vu[i]);
将成功地找到双运算符,但sum += static_cast<resultType>(vt[i]) * static_cast<resultType>(vu[i]);
将失败。
还有等功能
operator *( const class X &lhs, const class U & rhs )
{
return static_cast<double>(lhs) * static_cast<double>(rhs);
}
将有助于编译器。
如果您希望能够写入sum += vt[i] * vu[i];
,则必须定义T
和U
的乘积,方法是为这些类型定义返回double
的ad-hoc乘积,在这些类型上提供double
转换运算符,或者这些类型的组合。
为什么不使用在数字标头中定义的inner_product()算法?
内积算法计算两个长度相同的序列的内积。返回的值的类型由第四个参数决定。
#include <numeric>
#include <iostream>
#include <vector>
#include <functional>
#include <iomanip>
int main()
{
using namespace std;
vector<double> a{0, 1.1, 2, 3.1, 4};
vector<int> b{5, 4, 2, 3, 1};
double r1 = inner_product(begin(a), end(a), begin(b), 0.0);
cout << setiosflags(ios::fixed) << std::setprecision(5)
<< "Inner product of a and b: " << r1 << 'n';
}