【问题标题】:Type conversion from an expression to a double in C++ write a new operator**?在 C++ 中从表达式到双精度类型的转换写一个新的运算符**?
【发布时间】:2017-12-16 14:08:48
【问题描述】:

有一个泛型类 Vector 扩展了 std::array,还有一个泛型类 Expression 定义了向量的可能表达式。

例如:

向量 A({1,2,3});

向量 B({2,2,2});

和表达式:

A + B;

A * B;

A - B;

A / B;

现在我需要这个表达式 A ** B,它返回一个 double 作为两个向量 A 和 B 的标量产生,结果必须是:2+4+6=12。问题是operator**的实现!!!

我该如何写这个操作符**?

我的想法是重载 Vector 的解引用 operator* 返回一个指针,然后重载 struct-Mul oder multiply operator* ...无法解决此错误:

“不存在从“Expression, Mul, Vector *>”到“double”的合适转换函数”

template<typename Left, typename Op, typename Right> class Expression {
    const Left& m_left;
    const Right& m_right;

public:
    typedef typename Left::value_type value_type;

    // Standard constructor
    Expression(const Left& l, const Right& r) : m_left{ l }, m_right{ r } {}

    size_t size() const {
        return m_left.size();
    }

    value_type operator[](int i) const {
        return Op::apply(m_left[i], m_right[i]);
    }
};

struct Mul {
    template<typename T> static T apply(T l, T r) {
        return l * r;
    }
};

template<typename Left, typename Right>
Expression<Left, Mul, Right> operator*(const Left& l, const Right& r) {
    return Expression<Left, Mul, Right>(l, r);
}

.......................

// Class Vector extends std::array
template<class T, size_t S> class Vector : public array<T, S> {

public:
    // Standard constructor
    Vector<T, S>(array<T, S>&& a) : array<T, S>(a) {}

    // Initializerlist constructor
    Vector(const initializer_list<T>& data) {
        size_t s = __min(data.size(), S);
        auto it = data.begin();
        for (size_t i = 0; i < s; i++)
            this->at(i) = *it++;
    }
};

.....................................

int main {

    Vector<double, 5> A({ 2, 3, 4, 5, 6 });
    Vector<double, 5> B({ 3, 3, 3, 3, 3 });
    Vector<double, 5> C;
    C = A * B; // is a Vector: [6, 9, 12, 15, 18] and it works.

    double d = A**B;  // but this one does not work, the error message is: "no suitable conversion function from "Expression<Vector<double, 5U>, Mul, Vector<double, 5U> *>" to "double" exists"

    cout << d << endl; // must give me: 60
}

【问题讨论】:

  • 这几乎是不可能的,你最好重载另一个运算符,如右移或!
  • C++ 中没有operator**
  • 您不能使用** 表示法,因为C++ 没有** 运算符,也不支持定义全新的运算符。如果需要,您可以重载普通的单曲*。或者您可以定义一个伪运算符,如%dot%,这是一种滥用符号,其中第一个% 为您的向量和dot 的类型调用% 的重载,产生一些结果,然后将其传递给% 再次重载,第二个向量。但是为什么不考虑一个简单的命名函数呢?简单且可维护。
  • KIA 另一种方法是在私有类型上使用解引用运算符和乘法运算符

标签: c++ templates vector overloading


【解决方案1】:

我能够想出的一个非常快速且易于遵循的解决方案是:

class X
{
  class B
  {

  };
  B n;
public:

    B operator* ()
    {
        return this->n;
    }

    double operator * (B rhs)
    {
        cout<<"Here"<<endl;
        return 0;
    }
};

int main()
{
    X a;
    X b;

    a ** b;
}

这允许您将数据存储在 B 类中,然后根据需要使用它。

【讨论】:

    【解决方案2】:

    一点点类型滥用给你想要的:

    #include <vector>
    #include <type_traits>
    #include <cassert>
    #include <iostream>
    
    struct special_vector;
    
    struct star
    {
        star(special_vector& v) : vec(std::addressof(v)) {}
    
        special_vector* vec;
    };
    
    struct special_vector : std::vector<double>
    {
        using std::vector<double>::vector;
    
        auto operator*() -> star { return star(*this);}
    };
    
    
    auto operator*(special_vector const& l, star const& r) -> double
    {
        assert(l.size() == r.vec->size());
    
        double result = 0.0;
    
        auto fl = l.cbegin(), fr = r.vec->cbegin(), ll = l.cend();
        while (fl != ll)
        {
            result += (*fl++ * *fr++);
        }
    
        return result;    
    }
    
    
    int main()
    {
        auto v1 = special_vector{ 1, 2, 3 };
        auto v2 = special_vector{ 1, 2, 3 };
    
        auto ans = v1 ** v2;
    
        std::cout << ans << std::endl;
    }
    

    预期输出:

    14

    http://coliru.stacked-crooked.com/a/f831c7594421f37d

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-14
      • 1970-01-01
      • 2015-08-31
      • 1970-01-01
      • 2014-12-31
      • 1970-01-01
      相关资源
      最近更新 更多