jeudi 1 mars 2018

const template template parameter

I'm trying to design the following (very simplified) class:

template<int Dim, template<int,int> class Matrix>
class MatrixWrapperBase
{
    using InternalType Matrix<Dim,Dim>;
    InternalType member_;
public:
    // Provide additional functionalities
};

where Matrix is a generic template class implementing common matrix functionalities; in my specific case it is just a typedef of the Eigen::Matrix class:

template<int R, int C>
using MyMatrix = Eigen::Matrix<double,R,C>;

Now, I would like to provide both the non-const and the const InternalType version of this class (iterators-inspired) using aliases like:

template<int Dim>
using MatrixWrapper = MatrixWrapperBase<Dim,MyMatrix>;

template<int Dim>
using ConstMatrixWrapper = MatrixWrapperBase<Dim,const MyMatrix>;   // ERROR

I'm perfectly aware of the reasons why the latter does not compile (they are well explained in this answer, for instance template template class with const template parameter), so I tried to use another template-template argument alias for the const case:

template<int R, int C>
using MyConstMatrix = Eigen::Matrix<const double, R, C>;
...
template<int Dim>
using ConstMatrixWrapper = MatrixWrapperBase<Dim,MyConstMatrix>;

Unfortunately, Eigen refuse to compile when I try to instance a ConstMatrixWrapper object (or a MyConstMatrix object as well) because of the following error:

/usr/include/eigen3/Eigen/src/Core/PlainObjectBase.h:474:27: error: ‘static Eigen::PlainObjectBase<Derived>::MapType Eigen::PlainObjectBase<Derived>::Map(Eigen::PlainObjectBase<Derived>::Scalar*) [with Derived = Eigen::Matrix<const double, 2, 2>; Eigen::PlainObjectBase<Derived>::MapType = Eigen::Map<Eigen::Matrix<const double, 2, 2>, 0, Eigen::Stride<0, 0> >; Eigen::PlainObjectBase<Derived>::Scalar = const double]’ cannot be overloaded
     static inline MapType Map(Scalar* data)
                       ^
/usr/include/eigen3/Eigen/src/Core/PlainObjectBase.h:472:32: error: with ‘static Eigen::PlainObjectBase<Derived>::ConstMapType Eigen::PlainObjectBase<Derived>::Map(const Scalar*) [with Derived = Eigen::Matrix<const double, 2, 2>; Eigen::PlainObjectBase<Derived>::ConstMapType = const Eigen::Map<const Eigen::Matrix<const double, 2, 2>, 0, Eigen::Stride<0, 0> >; Eigen::PlainObjectBase<Derived>::Scalar = const double]’
     static inline ConstMapType Map(const Scalar* data)

I found a workaround by adding a bool template argument to the MatrixWrapperBase class to discriminate between the const and the non-const case in such a way:

template<bool Constness, int Dim, template<int,int> class Matrix>
class MatrixWrapperBase
{
    using InternalType = std::conditional_t<Constness, const Matrix<Dim,Dim>, Matrix<Dim,Dim>>;
    ...
};

template<int Dim>
using MatrixWrapper = MatrixWrapperBase<false,Dim,MyMatrix>;

template<int Dim>
using ConstMatrixWrapper = MatrixWrapperBase<true,Dim,MyMatrix>;

but I would like to avoid such a design, if possible.

Can anyone give me a hint? Thanks in advance.

Aucun commentaire:

Enregistrer un commentaire