c++ 用户定义类型的编译时表达式因子分解

jjjwad0x  于 2023-02-17  发布在  其他
关注(0)|答案(1)|浏览(121)

对于平凡类型,编译器可以将算术表达式优化为具有相同结果的新表达式,该表达式需要较少的指令来计算它。例如,如果a, bint,则表达式int c = a * a + b * a将计算为(a + b) * a,这节省了指令。
有没有办法告诉编译器对自定义类型执行这种优化?例如,如果A, B是矩阵,那么计算A*A + A*B将被分解为A*(A+B)(在编译时),这在运行时节省了大约n2个操作。

ff29svar

ff29svar1#

首先要注意,矩阵的A*A + A*B != (A+B)*A,甚至不接近,它是A*(A+B),这和矩阵乘法不交换不一样,也就是说,你所要求的,作为一个概念上的东西,是可行的。
这不是一个完整的答案,只是一个提示。正如@JerryJeremiah正确地写的那样,你可以使用表达式模板。首先对于你的矩阵类,你返回一个未求值的上下文,而不是实现表达式求值的运算符:(这里我展示值scemantics,当然,你可以使用引用/指针来实现它)

template<typename LHS, typename RHS, char op>
struct OperatorContext {
    static constexpr char operator = op;
    const LHS lhs;
    const RHS rhs;
};

// inside Matrix {
    template<typename LHS, typename RHS, char op>
    friend auto operator+(const Matrix& lhs, OperatorContext<LHS, RHS, op>& rhs) {
        return OperatorContext<Matrix, OperatorContext<LHS, RHS, op>, '+'>{lhs, rhs};
    }

    template<typename LHS, typename RHS, char op>
    friend auto operator+(OperatorContext<LHS, RHS, op>& lhs, const Matrix& rhs) {
        return OperatorContext<Matrix, OperatorContext<LHS, RHS, op>, '+'>{lhs, rhs};
    }

    friend auto operator+(const Matrix& lhs, const Matrix& rhs) {
        return OperatorContext<Matrix, Matrix, '+'>{lhs, rhs};
    }

    // similarly for other operators
// }

// furthermore, you need similar operators for 2 OperatorContext arguments

然后,您可以从不同的OperatorContext<>版本中实现Matrix的赋值运算符。在这里,您可以进行优化,因为您有完整的类型信息。请注意,只有在您为变量赋值之前,此操作才有效。例如:

// inside Matrix {
    Matrix& operator=(OperatorContext<OperatorContext<Matrix, Matrix, '*'>, OperatorContext<Matrix, Matrix, '*', '+'> other) {
        if (other.lhs.lhs == other.rhs.lhs) { // preferably compare-by-address
          *this = other.lhs.lhs * (other.lhs.rhs + other.rhs.rhs)
        } else {
          *this = other.lhs.lhs * other.lhs.rhs + other.rhs.lhs * other.rhs.rhs;
        }
        return *this;
    }
// }

相关问题