【问题标题】:How could comma separated initialization such as in Eigen be possibly implemented in C++?诸如 Eigen 中的逗号分隔初始化如何可能在 C++ 中实现?
【发布时间】:2015-06-13 21:51:55
【问题描述】:

这是 Eigen 文档的一部分:

Matrix3f m;
m << 1, 2, 3,
     4, 5, 6,
     7, 8, 9;
std::cout << m;

输出:

1 2 3
4 5 6
7 8 9

我不明白上面的操作符

cout << "Just commas: ";
cout << 1, 2, 3, 4, 5;
cout << endl;
cout << "Commas in parentheses: ";
cout << ( 1, 2, 3, 4, 5 );
cout << endl;

可以预见(根据我对 C++ 语法的理解)只有一个值被 operator 捕获

Just commas: 1
Commas in parentheses: 5

因此标题问题。

【问题讨论】:

  • 他们很可能已经超载了operator,() 以允许这样做。
  • 找到this源代码。

标签: c++ initialization operator-overloading eigen


【解决方案1】:

基本思想是重载&lt;&lt;, 运算符。

m &lt;&lt; 1 被重载以将1 放入m,然后返回一个特殊的代理对象——称之为p——持有对m 的引用。

然后p, 2被重载将2放入m并返回p,这样p, 2, 3将首先将2放入m然后3

Boost.Assign 使用了类似的技术,尽管它们使用 += 而不是 &lt;&lt;

【讨论】:

    【解决方案2】:

    这是一个可能的简化实现

    struct M3f {
        double m[3][3];
        struct Loader {
            M3f& m;
            int i;
            Loader(M3f& m, int i) : m(m), i(i) {}
            Loader operator , (double x) {
                m.m[i/3][i%3] = x;
                return Loader(m, i+1);
            }
        };
        Loader operator<<(double x) {
            m[0][0] = x;
            return Loader(*this, 1);
        }
    };
    

    想法是&lt;&lt;返回一个等待第二个元素的Loader实例,每个加载器实例使用逗号操作符更新矩阵并返回另一个加载器实例。

    请注意,重载逗号运算符通常被认为是一个坏主意,因为运算符最具体的特征是严格的从左到右的评估顺序。但是,当重载时,这并不能保证,例如在

    m << f(), g(), ...
    

    g() 最终可能会在 f() 之前被调用。

    请注意,我说的是评估顺序,而不是关联性或优先级,当然也为重载版本维护。 例如,g() 可以在f() 之前调用,但f() 的结果保证在g() 的结果之前正确放置在矩阵中。

    【讨论】:

    • 为什么operator,重载时顺序不保持? m &lt;&lt; f(), g() 不只是运算符的组合,有严格的从左到右求值的规则吗?
    • @vsoftco:,&amp;&amp;|| 的重载版本不保证评估顺序(本机版本保证评估顺序的唯一运算符) .您不应将评估顺序与关联性和优先级(当然由重载版本维护)混淆。换句话说,g() 可能会在 f() 之前被调用,但来自 f() 的值将被插入到矩阵中 g() 的值之前。
    • 谢谢,你说得对,我意识到我实际上是在考虑关联性。
    【解决方案3】:

    逗号本身是 c++ 中的一个运算符,可以重载(显然是由 eigen 实现的)。我不知道 eigen 实现重载的确切方式,但我相信您可以搜索 eigen 的来源进行查找。

    对于您的小经验,您必须了解un重载的逗号运算符在 c++ 中的工作原理。

    逗号运算符的格式为&lt;statement&gt;,&lt;statement&gt;,并根据second 语句的求值结果进行求值。运算符&lt;&lt; 的优先级高于运算符,。因此,cout 在评估其余逗号操作之前先评估。

    因为, 是从左到右关联的,所以代码(1,2,3,4,5) 等于((((1,2),3),4),5),它的计算结果是最右边的值,即5

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-12-09
      • 1970-01-01
      • 2015-08-11
      • 2018-08-05
      • 2018-06-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多