试图为Eigen Matrix实现一种初始化列表语法

问题描述 投票:3回答:2

我喜欢Eigen的逗号初始化语法,但我更喜欢它类似于初始化列表初始化。

我试图自己实现这样的事情,但我遇到了一些我无法解决的问题。

我的方法如下:

#include <iostream>
#include <Eigen/Dense>

template <int Rows= Eigen::Dynamic, int Cols= Rows>
class MyMatrix: public Eigen::Matrix<double,Rows,Cols>
{
private:
  using Matrix= Eigen::Matrix<double,Rows,Cols>;

public:
  MyMatrix(): Matrix() {
    std::cout << "MyMatrix()\n";
    if /* constexpr */ (Rows!=Eigen::Dynamic) Matrix::setZero(); }

  template <typename Derived>
  MyMatrix(const Eigen::MatrixBase<Derived> &Other): Matrix(Other) // (2)
    { std::cout << "MyMatrix(const MatrixBase<Derived> &Other)\n"; }

  template <typename TFirst,typename... TRest/*,typename= enable_if_t<NoIdea::value>*/>
  MyMatrix(TFirst &&First,TRest &&... Rest) { *this << First, (Rest, ...); }
};

int main()
{
MyMatrix<3> Mat1= MyMatrix<3>::Identity();
MyMatrix<3> Mat2= { MyMatrix<3>::Identity() };
MyMatrix<3> Mat3= { 1.0, 0.0, 0.0, // Runtime error
                    0.0, 1.0, 0.0,
                    0.0, 0.0, 1.0 };
MyMatrix<3> Mat4= MyMatrix<3>::Identity()+MyMatrix<3>::Ones();
MyMatrix<3> Mat5= {};
}

这段代码用g ++ - 6编译,但它有(至少)两个问题:

  1. 从不调用构造函数(2),我不知道如何鼓励编译器为适当的对象选择它。
  2. 我得到一个断言失败的MyMatrix实例实际上使用初始化列表(qazxsw poi)。似乎折叠表达式不能像我想的那样工作。

任何帮助将非常感激。

c++ variadic-templates eigen c++17
2个回答
1
投票

我刚刚意识到fold表达式中的错误。它应该是:

Too few coefficients passed to comma initializer (operator<<)

编辑:由于我对使用单个元素的init-lists不感兴趣,以下解决方案避免了构造函数歧义问题:

(*this << First),...,Rest;

不幸的是,这段代码不能用g ++ - 6编译(可能是因为template <typename TFirst,typename TSecond,typename... TRest> MyMatrix(TFirst &&First,TSecond &&Second,TRest &&... Rest) { ((*this << First, Second), ... , Rest); } ),但它与clang ++ - 3.8一起编译。

现在我可以写:

bug 68377

代替:

MyMatrix<3> m= { MyMatrix<2,2>::Ones(), MyMatrix<2,1>::Zero(),
                 MyMatrix<1,2>::Zero(), 0.0 };

1
投票

这是我提出的解决方案:

MyMatrix<3> m= ( MyMatrix<3>() << MyMatrix<2,2>::Ones(), MyMatrix<2,1>::Zero(),
                                  MyMatrix<1,2>::Zero(), 0.0 ).finished();

其中// very dark magic template<int M, int N=M> constexpr auto MakeMatrix = [](auto m, auto... ms) { return ((Matrix<M,N>()<<m),...,ms).finished(); }; 是:

Matrix<M,N>

用法如下:

template<int M, int N=M>
using Matrix = Eigen::Matrix<double, M, N>;

(输出)

auto v = Matrix<2,1>::Zero();
auto m = Matrix<2>::Identity();
std::cout<< MakeMatrix<2,3>(v,m);
© www.soinside.com 2019 - 2024. All rights reserved.