[英]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.