所述阵列背后的原理是模拟2D / 3D像素矩阵。
经过大量研究和阅读后,我认为Boost.MultiArray可能会派上用场。但是,我仍然必须在其顶部创建一个简洁的包装,以减少冗长的编码。
最终,我想实现以下目标:
PixMat<u8, 3, {2, 4, 3}> pixMat;
或
PixMat<u8, 3> pixMat(2,3,4);
,它将基本上创建一个2x4x3的u8值矩阵。
到目前为止,我想出的是:
template <typename T, int Dims>
class PixMat {
public:
typedef typename boost::multi_array<T, Dims> PixMatType;
typedef typename PixMatType::index PixMatTypeIdx;
PixMat(int dim1Ext, int dim2Ext) : pixMat(PixMatType(boost::extents[dim1Ext][dim2Ext])) {}
PixMat(int dim1Ext, int dim2Ext, int dim3Ext) : pixMat(PixMatType(boost::extents[dim1Ext][dim2Ext][dim3Ext])) {}
private:
PixMatType pixMat;
};
template <typename T>
class Pix2DMat : PixMat<T, 2> {
public:
Pix2DMat(int dim1Ext, int dim2Ext) : PixMat<DataType, 2>(dim1Ext, dim2Ext) {}
};
template <typename T>
class Pix3DMat : PixMat<T, 3> {
public:
Pix3DMat(int dim1Ext, int dim2Ext, int dim3Ext) : PixMat<DataType, 3>(dim1Ext, dim2Ext, dim3Ext) {}
};
我不太喜欢这种解决方案。通常,矩阵既不是2D也不是3D,但我仍然希望有一个更通用的解决方案。
问题:
typedef
来提升效率呢?答案 0 :(得分:1)
我认为您可以使用以下几种技术:
可变构造函数参数
您可以使用可变参数技术来创建通用的N维构造函数,而不是为每个可能的维使用单独的构造函数。在这里是您的朋友:构造器参数不需要boost::extents
,而是满足Collection要求的任何东西。一个例子就是普通的STL或boost数组:
template <typename... DimSizes>
PixMat(DimSizes&&... sizes)
: pixMat(boost::array<std::size_t, sizeof...(DimSizes)>{{ static_cast<size_t>(sizes)...}}) {
}
这不是最完善的实现;特别是对DimSizes并没有太多要求,DimSizes实际上应该都是相同的无符号整数类型(有关可能的改进,请参见this question)。同样(为简单起见),没有实现完美的转发,但这可能只需要在构造函数中将sizes
与std::forward<DimSizes>(sizes)
包装在一起即可。
您可以咨询this stackoverflow post以获得可能的替代实施方式。
静态声明/ SFINAE
您的模板基类具有2D构造函数和3D构造函数---或者,如果遵循上述内容,则具有模板N维构造函数---而不管实际模板参数的值如何。您可以使用静态断言或SFINAE,以便仅Dims-D维构造函数是可编译的。这会将运行时错误转换为编译错误:
template <typename... DimSizes>
PixMat(DimSizes&&... sizes)
: pixMat(boost::array<std::size_t, sizeof...(DimSizes)>{{ static_cast<size_t>(sizes)...}}) {
static_assert(sizeof...(DimSizes) == Dims);
}
尺寸尺寸作为模板
我认为这是可能的,尽管是完全正交的解决方案。它的实现将从上面开始,无需太多工作,但是要使其与基于构造函数自变量的解决方案互操作,将需要进行大量艰苦的工作(即,使它们成为同一类或类层次结构的一部分)。
其他库
例如,您可能想看看Eigen。它完成了许多上述艰苦的工作。
答案 1 :(得分:1)
如果我对您的理解正确,那么您需要编译时维度,但需要运行时范围。
我会使用这样的设计:
<img onMouseEnter={this.handleHover} onMouseLeave={this.handleLeave} className={`${this.state.highlight}`} src="img" />
<img onMouseEnter={this.handleHover} onMouseLeave={this.handleLeave} className={`${this.state.highlight}`} src="img" />
数据存储在template <typename T,std::size_t Dim>
class mdvector
{
private:
std::vector<T> Data;
std::array<std::size_t,Dim> Extents;
private:
std::size_t Offset(std::size_t const Sum) const
{ return Sum; }
template <typename... IndexType>
std::size_t Offset(std::size_t const Sum,std::size_t const Index,IndexType const... Indices) const
{ return Offset(Sum*Extents[Dim-sizeof...(Indices)-1u]+Index,Indices...); }
public:
template <typename... IndexType,typename= std::enable_if_t<sizeof...(IndexType)==Dim>>
mdvector(IndexType const... Indices):
Data((... * Indices)), // c++17 fold expression
Extents{Indices...} {}
template <typename... IndexType,typename= std::enable_if_t<sizeof...(IndexType)==Dim>>
T const &operator()(IndexType const... Indices) const
{ return Data[Offset(0u,Indices...)]; }
template <typename... IndexType,typename= std::enable_if_t<sizeof...(IndexType)==Dim>>
T &operator()(IndexType const... Indices)
{ return Data[Offset(0u,Indices...)]; }
};
中,而扩展区构成std::vector
。
由于我假设您要进行多维访问,因此我通过递归函数std::array
使用了给定的映射。您在这方面有很大的自由度。
这是一个使用示例:
Offset
由于扩展区是动态的,因此您可以在运行时更改它们,例如:
int main()
{
mdvector<double,3u> myvec(2u,3u,4u);
for (int i= 0; i<2; ++i)
for (int j= 0; j<3; ++j)
for (int k= 0; k<4; ++k)
myvec(i,j,k)= i;
for (int k= 0; k<4; ++k)
{
for (int i= 0; i<2; ++i)
{
for (int j= 0; j<3; ++j)
std::cout << myvec(i,j,k) << "\t";
std::cout << "\n";
}
std::cout << "\n";
}
}
反之,如果您更喜欢范围作为模板参数,则它们应该在运行时保持固定。在这种情况下,您可以将它们包括在类声明中:
template <typename T,std::size_t Dim>
template <typename... IndexType,typename= std::enable_if_t<sizeof...(IndexType)==Dim>>
void mdvector<T,Dim>::Resize(IndexType const... Indices)
{ Data.resize((... * Indices)); Extents= {Indices...}; }
,但实现方式几乎相同。请注意,不必指定尺寸,因为您可以使用template <typename T,std::size_t... Indices>
class mdvector { /* ... */};
来获得尺寸。
上面的代码中的fold表达式不是严格必需的。通过以下方式可以达到相同的结果:
sizeof...(Indices)