C++ 表达式模板不明确的运算符重载

标签 c++ expression-templates

我正在尝试实现 vector 和矩阵表达式模板。两者都有 operator+ 重载,但我遇到了不明确的运算符错误。

如何在保留表达式模板效果的同时重载矩阵和 vector 的运算符?

这是我的矩阵求和模板:

    template<typename E1, typename E2>
class MatSum: public MatExpression<MatSum<E1,E2>>{
    E1 const& _u;
    E2 const& _v;

public:
    MatSum(E1 const &u, E2 const &v): _u(u), _v(v){
        assert(u.height() == v.height() && u.width() == v.width());
    }

    double operator[](size_t i) const {return _u[i] + _v[i]; }

    size_t size() const {return _u.size();}
    size_t width() const {return _u.width();}
    size_t height() const {return _u.height();}
};

template<typename E1, typename E2>
MatSum<E1,E2> operator+(E1 const& u, E2 const& v){
    return MatSum<E1,E2>(u,v);
}

这里是 vector 和模板:

template <typename E1, typename E2>
class VecSum : public VecExpression<VecSum<E1, E2>>{
    E1 const& _u;
    E2 const& _v;

public:
    VecSum(E1 const & u, E2 const &v): _u(u), _v(v){
        assert(u.size() == v.size());
    }

    double operator[](size_t i) const {return _u[i] + _v[i]; }
    size_t size() const {return _v.size(); }
};


template <typename E1, typename E2>
VecSum<E1, E2> operator+(E1 const &u, E2 const &v){
    return VecSum<E1,E2>(u,v);
}

以及导致错误的代码段:

    Vec v1 = {67.12,34.8,90.34};

    Vec v2 = {34.90,111.9,45.12};

    Vec sum = v1+v2;

Matrix m0 = {{1.0,1.0,1.0},{1.0,1.0,1.0},{1.0,1.0,1.0}};
    Matrix m1 = {{1.0,1.0,1.0},{1.0,1.0,1.0},{1.0,1.0,1.0}};

    Matrix summ = m0 + m0;

最佳答案

模板不能特化返回类型。

在您的情况下,编译器无法选择调用哪个 operator+,因为它们都可以用任何两种类型实例化。 考虑这些例子:

Vec v1 = {67.12,34.8,90.34};
Matrix m1 = {{1.0,1.0,1.0},{1.0,1.0,1.0},{1.0,1.0,1.0}};
auto sum = v1+m1;

这里应该调用两个运算符中的哪一个?这对编译器来说是模棱两可的。

你可以制作两个非模板运算符+,它们有(Vec, Vec)(Matrix, Matrix) 参数或使用SFINAE检查某些条件的模板运算符参数类型并替换所需的 operator+ 特化。

关于C++ 表达式模板不明确的运算符重载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55476529/

相关文章:

c++ - 如何计算插值三角曲面的主曲率?

c++ - C++ 编译器内联函数局部 lambda 的效率如何?

c++ - 异步 cppcms session 。模式

c++ - 表达式模板未完全内联

c++ - 模板类成员方法内的自动 lambda : does not name a type

c++ - 如何检测win32应用程序中显示器的热插拔?

c++ - 避免需要使用表达式模板进行#define

c++ - 使用 O3 解决表达式模板段错误

C++ 表达式模板——为什么是基类?

c++ - Boost.Proto:如何制作原始数组的表达式终端而不是 std::vector?