const模板模板参数

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

我正在尝试设计以下(非常简化)类:

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

其中Matrix是实现通用矩阵功能的通用模板类;在我的具体情况下,它只是Eigen::Matrix类的typedef:

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

现在,我想使用以下别名提供此类的非constconst InternalType版本(迭代器启发):

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

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

我完全清楚后者不能编译的原因(在这个答案中很好地解释了,例如template template class with const template parameter),所以我尝试使用const案例的另一个模板模板参数别名:

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

不幸的是,当我尝试实例化ConstMatrixWrapper对象(或MyConstMatrix对象)时,Eigen拒绝编译,因为以下错误:

/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)

我找到了一个解决方法,通过在bool类中添加一个MatrixWrapperBase模板参数,以这种方式区分const和非const案例:

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

但如果可能的话,我想避免这样的设计。

任何人都可以给我一个提示吗?提前致谢。

c++ c++11 templates eigen3 template-templates
2个回答
0
投票

我建议:

template <typename M> struct MatrixWrapperHelper;

template<int D1, int D2, template<int,int> class Matrix>
struct MatrixWrapperHelper<Matrix<Dim1, Dim2>>
{
    template <int NewDim1, int NewDim2>
    using ResizedType = Matrix<NewDim1, NewDim2>;

    static constexpr int Dim1 = D1;
    static constexpr int Dim2 = D2;
};


template <typename M> class MatrixWrapperBase
{
    using MatrxType = std::decay_t<M>;
    // MatrixWrapperHelper<MatrxType>::Dim1
    // typename MatrixWrapperHelper<MatrxType>::template Resized<42, 42>

    using InternalType = M;
    M member_;
public:
    // Provide additional functionalities
};

最后:

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

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

0
投票

我找到了一个解决方法,通过在MatrixWrapperBase类中添加一个bool模板参数来以这种方式区分const和非const的情况[...]但是如果可能的话我想避免这样的设计。

额外的bool模板参数有什么问题?

无论如何,你可以使用部分模板特化默认bool模板值来获得类似的东西。

以下是完整的编译示例

#include <type_traits>

template <int, int>
struct Mtx
 { };

template <typename T, bool = false, bool = std::is_const<T>::value>
struct MatrixWrapperBase 
 { };

template <int Dim, template <int,int> class Matrix, bool C>
struct MatrixWrapperBase<Matrix<Dim, Dim>, C, false>
 {
   using InternalType = typename std::conditional<C,
            Matrix<Dim, Dim> const, Matrix<Dim, Dim>>::type;
 };

template <typename T>
struct MatrixWrapperBase<T, false, true>
   : public MatrixWrapperBase<typename std::remove_const<T>::type,
                              true, false>
 { };

int main()
 {
   MatrixWrapperBase<Mtx<1, 1>>        mwb;
   MatrixWrapperBase<Mtx<1, 1> const>  cmwb;

   static_assert( std::is_same<typename decltype(mwb)::InternalType,
                               Mtx<1, 1>>{}, "!");
   static_assert( std::is_same<typename decltype(cmwb)::InternalType,
                               Mtx<1, 1> const> {}, "!");

 }
© www.soinside.com 2019 - 2024. All rights reserved.