簡體   English   中英

如何在 C++ 中實現諸如 Eigen 中的逗號分隔初始化?

[英]How could comma separated initialization such as in Eigen be possibly implemented in C++?

這是 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

我無法理解上面的 operator<< 如何捕獲所有逗號分隔值。 我做了一個小實驗:

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

因此標題問題。

基本思想是重載<<,運算符。

m << 1被重載以將1放入m ,然后返回一個特殊的代理對象——稱之為p持有對m的引用。

然后p, 2被重載以將2放入m並返回p ,這樣p, 2, 3將首先將2放入m然后再放入3

Boost.Assign使用了類似的技術,盡管它們使用+=而不是<<

這是一個可能的簡化實現

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);
    }
};

這個想法是<<返回一個等待第二個元素的Loader實例,每個 loader 實例使用逗號運算符來更新矩陣並返回另一個 loader 實例。

請注意,重載逗號運算符通常被認為是一個壞主意,因為運算符最具體的特征是嚴格的從左到右的計算順序。 但是,當超載時,這不能保證,例如在

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

g()最終可能會在f()之前被調用。

請注意,我在談論評估順序,而不是關於當然也為重載版本維護的關聯性或優先級。 例如g()之前可以被稱作f() ,但是從結果f()保證被正確地放置在基體中的結果之前,從g()

逗號本身是 C++ 中的一個運算符,可以重載(顯然是由本征)。 我不知道 eigen 實現重載的確切方式,但我相信您可以搜索 eigen 的來源來查找它。

對於您的小經驗,您必須了解重載的逗號運算符如何在 C++ 中工作。

逗號運算符的形式為<statement>,<statement>並計算為第二個語句的計算結果。 運算符<<的優先級高於運算符, 因此,在評估其余逗號操作之前先評估cout

因為,是從左到右關聯的,所以代碼(1,2,3,4,5)等於((((1,2),3),4),5) ,它的計算結果是最右邊的值,這是5

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM