ユーザ型をEigen::Matrixへ変換するoperatorがうまく働かない
問題
次のようなコードを書いた.
ubuntu 16.04
struct pose { explicit operator Eigen::Matrix4f () const { Eigen::Translation3f translation(x, y, z); Eigen::AngleAxisf rotation_x(roll, Eigen::Vector3f::UnitX()); Eigen::AngleAxisf rotation_y(pitch, Eigen::Vector3f::UnitY()); Eigen::AngleAxisf rotation_z(yaw, Eigen::Vector3f::UnitZ()); return (translation * rotation_z * rotation_y * rotation_x).matrix(); } };
姿勢情報(x,y,z,roll,pitch,yaw) を剛体変換行列へ変換するoperatorを実装したのだが,思ったように使えなかった.
pose p; auto m = static_cast<Eigen::Matrix4f>(p); // compile error!!!
error: no matching function for call to 'Eigen::Matrix::_init1(const pose&)'
EigenのMatrixはコンストラクタによる初期化じゃなくてinitっていう関数へ置き換えられている...? それが何らかの理由でoperatorの呼び出し優先度よりも高くなってしまっているみたい.
理由
https://forum.kde.org/viewtopic.php?f=74&t=137768
Eigenのバージョン3.3では,Eigen::Matrixについて次のようなコンストラクタが定義されているみたい.
template <typename T> explicit Matrix(const T& x) {...}
これによって static_cast<Eigen::Matrix4f>(p)
に対応する呼び出しがこのコンストラクタになってしまう.
解決策1(バージョン変更)
c++ - Conversion operator in Eigen - Stack Overflow
どうやらバージョンの問題らしい.
ubuntu 16.04でインストールしたもののバージョンが3.2.92
だったが,3.2.6
を使うとよいらしい.
解決策2 (明示的なキャストをやめる)
Eigen::Matrix4f m = p;
こうすると,operatorの方がきちんと呼ばれる.ただし,explicit
は外しておく必要がある.
struct pose { operator Eigen::Matrix4f () const {...} };
しかし文法が変わってしまうので,テンプレートパラメータとしてEigen::Matrix4f
を渡したときに少し困る.
これは,Eigen用の特殊化をするか,Eigen Matrix自体をラップするラッパークラスを作るような解決策が考えられる.