【问题标题】:Range-v3 operator overloading to write shorter codeRange-v3 运算符重载以编写更短的代码
【发布时间】:2019-07-09 21:32:15
【问题描述】:

对于我的矩阵类,我想在+ - / * % 的 range-v3 视图上执行某种运算符重载(可能使用表达式模板)。 例如,如果我想查看两列的总和,我想写

col_1 + col_2

而不是

rv::zip_with([](auto c1, auto c2) {return c1 + c2;}, col_1, col_2);

可能来自paper 的一些想法可以用来避免构建太多的临时对象。这是我要写的代码:

//simple example
//what I want to write
auto rangeview =    col_1 + col_2;
//what I can write
auto rangeview =    rv::zip_with([](auto c1, auto c2) {
                        return c1 + c2;
                    }, col_1, col_2);


//itermediate
//what I want to write
auto rangeview =    col_1 + col_2 + col_3;
//what I can write
auto rangeview =    rv::zip_with([](auto c1, auto c2, auto c3) {
                        return c1 + c2 + c3;
                    }, col_1, col_2, col_3);


//advanced
//what I want to write
auto rangeview =    10*col_1 + 20*col_2 - 30*col_3;
//what I can write
auto rangeview =    rv::zip_with([](auto c1, auto c2, auto c3) {
                        return 10.0*c1 + 20.0*c2 - 30.0*c3;
                    }, col_1, col_2, col_3);


//more advanced with elementwise multiplication
//what I want to write
auto rangeview =    10*col_1 + 20*col_2 - col_2 % col_3;
//what I can write
auto rangeview =    rv::zip_with([](auto c1, auto c2, auto c3) {
                        return 10.0*c1 + 20.0*c2 - c2*c3;
                    }, col_1, col_2, col_3);

【问题讨论】:

  • 这是一个非常非常广泛的问题。您所要求的实际上是一个表达式模板库 - 并且有许多大型库试图在各个领域解决此类问题。
  • 那么中间示例(只是添加任意数量的视图)呢?还是太宽泛了?
  • 常规运算符重载有什么问题?
  • 通过常规重载,您必须按照上面的论文(第 11 页)中的说明构建临时对象。
  • 您可以使用std::plus<>(或ranges::plus)来简化一点。

标签: c++ operator-overloading c++17 range-v3


【解决方案1】:

您主要关心的似乎是(可能很大)可以创建的临时对象。这可以通过一个称为表达式模板的概念来解决,但这里并没有真正的一刀切解决方案。最好的选择可能是切换到支持它的矩阵库。除非您正在开发一个库或想要对此进行投资,否则您可能不想编写自己的表达式模板。一种更简单但没有大量运算符重载/表达式模板的方法是使用具有自定义迭代类型的基于范围的 for 循环(不像表达式模板那样在语法上很简单,但更容易实现):

伪代码:

*resultype* result;//perhaps alloc on this line or make zip handle it..
for (auto z : zip(result, col_1, col_2, col_3)) {
  z[0] = 10.0*z[1] + 20.0*z[2] - 30.0*z[3];
}

这是在构思阶段,但会比 lambda 风格短一点(恕我直言,读起来更愉快)。 如何实现 zip 类我没有回答这个问题。

【讨论】:

    【解决方案2】:

    我同意@darune,除非你有强烈的需求,否则你应该使用库,尤其是 Eigen。您想支持的大部分操作都在This link 上进行了说明。

    【讨论】:

    • 我将 Armadillo 用于我的数字矩阵 - 但对于每个单元格是 std::string、double、bool、...的 std::variant 的单元格矩阵,我需要此功能>
    • 这类似于数据框吗?从上面你得到10.0*c1 + 20.0*c2 - c2*c3;,你是为std::string或std::bool做的吗?
    • 把它想象成一个 Excel-Cell-Matrix,其中一些列是数字,而另一些则不是......
    • 啊,好吧,在这种情况下,您需要实现自己的表达式模板以避免复制,这并不简单并且需要一些努力(这就是 Eigen 和 Armadillo 正在做的事情)。但是副本也不是一件可怕的事情,例如 numpy 运行速度非常快并且到处都可以复制。当您需要数百万次执行某些运算符时,表达式模板会更有用。
    • @Porsche9II 电子表格程序会缓存值(实际上存在暂停重新评估的情况,例如电子表格作为 MIME 对象包含在另一个文档中。)它们使用“公式”对象的概念。此外,电子表格通常具有相对和绝对寻址,这是有史以来第一个电子表格程序的标准行为。例如在包含“A1”的 Excel 公式中,其行为与“$A$1”不同。如果您复制到其他单元格,前者会改变
    猜你喜欢
    • 1970-01-01
    • 2014-12-10
    • 2011-01-24
    • 2021-10-27
    • 2011-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多