【问题标题】:Defining conversion from a class to double定义从类到双精度的转换
【发布时间】:2015-12-29 11:32:52
【问题描述】:

我想知道是否有办法解决这个问题,或者至少有更好的方法来完全使用模板:

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;
}

TU 应该是数字,例如 double、int 或任何其他支持这些操作的类(我是模板新手)。

有没有办法摆脱这个convert() 函数(它获取特定类的数字成员)而只写sum += vt[i] * vu[i]

【问题讨论】:

    标签: c++ templates type-conversion


    【解决方案1】:

    如果将所有TUvt[i]vu[i] 的隐式转换运算符定义为double(或一个到double 和另一个可以提升为double 的类型)将转换为doubles,乘法的结果将是double,随心所欲。

    例子:

    class Foo
    {
        double value;
    
    public:
        // ...
    
        operator double() const { return value; }
    };
    

    但你必须决定返回什么。

    【讨论】:

      【解决方案2】:

      我觉得你有点希望。

      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+= 的 2 个版本会产生不同的结果。如果 sum 是整数,则可能会发生截断。

      在 double 和 int 的乘法中,类型提升发生在一个中,但在另一个中进行规范化。

      更新

      使用 resultType = double T 和 U 是双倍的 - 那么结果是一样的。

      T 是整数 U 是双精度数。 T 升职加倍,结果是一样的。

      T 和 U 是整数。 sum += static_cast&lt;double&gt;( 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 += 将起作用,而第二个依赖于至少一个数字类型,因此编译器可以尝试显式 double 转换。

      如果有两个class,那么sum += static_cast&lt;resultType&gt;(vt[i]) * static_cast&lt;resultType&gt;(vu[i]); 将成功找到双重运算符,但sum += static_cast&lt;resultType&gt;(vt[i]) * static_cast&lt;resultType&gt;(vu[i]); 将失败。

      也是一个函数比如

      operator *( const class X &lhs, const class U & rhs )
      {
      
          return static_cast<double>(lhs) * static_cast<double>(rhs);
      }
      

      会帮助编译器。

      【讨论】:

      • 这两个版本有什么区别?
      • @user3650284 TU 是否有可能都是整数?如果是,您如何存储返回值?如果是double,为什么?
      • 我选择了double,因为我不知道如何使用模板制作版本。两者都有可能是整数。我只是好奇这些版本之间有什么区别?
      • 虽然你给了我这两个版本,但我每次都得到相同的结果(用 5.3 * 3.7 试过你的例子,我总是得到 19)。
      【解决方案3】:

      如果您希望能够编写 sum += vt[i] * vu[i];,则必须定义 TU 的乘积,或者通过为这些定义返回 doublead-hoc 乘积类型,通过为这些类型或这些类型的某种组合提供double 转换运算符。

      【讨论】:

        【解决方案4】:

        为什么不使用在数字标头中定义的 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';
        
        
        }
        

        【讨论】:

        • 1.容器不必具有相同的大小。 2. 我不只使用内置类型。
        • @user3650284 第二个 b 范围,与上面的范围一样多的元素 b = [begin(a), end(a))。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-08-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-07-08
        相关资源
        最近更新 更多