[英]Template Specifications for constructor of n-dimensional array
我正在实现一个n维数组类,它是一个模板如下(请注意,数据存储在一个线性数组中,其长度是所有维度的乘积):
template< class valType, int rank >
class NDimensionalArray
{
public:
private:
valType* m_data;
int* m_dimensions;
int m_rank;
};
所以我的想法是用户(我)可以指定排名2和某个维度的数组,即:
NDimensionalArray<double,2> matrix(10,10);
现在困难在于专门构造1-> n维的构造函数,每个构造函数需要n个参数,其中n是数组的等级。 现在我想到使用像printf()中使用的valarray,但是这个定义了一个具有2维的1维数组,即:
NDimensionalArray<double,1> matrix(10,10);
是完全可以接受的行为。 我可以使用一些巧妙的技巧让编译器重复吗? 实际上只要我知道排名,并且具有每个维度的长度,构造函数就可以是通用的:
{
int nElements = m_dimensions[0];
for ( int i=1 ; i<m_rank ; ++i )
nElements *= m_dimensions[i];
m_data = new valType[nElements];
}
编辑:请注意,访问者将需要类似的操作。
此外,我已经考虑了一个构造函数的选项,看起来像:
NDimensionalArray( const NDimensionalArray<int,1>& dimensions );
可以使用如下:
NDimensionalArray<int,1> dimVec(2); // Need a specification for 1-dimensional arrays.
dimVec(0) = 10;
dimVec(1) = 10;
NDimensionalArray<double,2> matrix(dimVec);
这将是一个可行的解决方案,但与我想要的用途相比它很难看。 访问多维数组也会变得非常痛苦,并且必须为每次访问构建维度向量非常慢。
好的,我已经玩了一段时间了。 这是一些模板元编程hackery,它可以完成你想要的东西。 它允许您指定内联的所有维度,它不执行任何动态内存分配或其他此类事情。 另外,使用一个好的C ++编译器(我使用VC ++ /O2
选项测试),代码将完全内联,没有完成复制(事实上,对我来说,它在调用时内联整个NDimensionalArray构造函数)。 它会在编译时完全进行类型检查,并且不会让你传递太少或太多的维度。 它可以重复用于索引器。 开始:
template<class T, int N>
class value_pack : private value_pack<T, N-1>
{
public:
enum { size = N };
value_pack(value_pack<T, N-1> head, const T& tail)
: value_pack<T, N-1>(head)
, value(tail)
{
}
value_pack<T, N+1> operator() (const T& tail) const
{
return value_pack<T, N+1>(*this, tail);
}
template<int I>
const T& get() const
{
return this->value_pack<T, I+1>::value;
}
protected:
const T value;
};
template<class T>
struct value_pack<T, 0>
{
};
struct
{
template <class T>
value_pack<T, 1> operator() (const T& tail) const
{
return value_pack<T, 1>(value_pack<T, 0>(), tail);
}
} const values;
template <class ValType, int Rank>
struct NDimensionalArray
{
NDimensionalArray(value_pack<ValType, Rank> values)
{
// ...
}
};
int main()
{
NDimensionalArray<int, 3> a(values(1)(2)(3));
}
我认为最好的解决方案是采用一个int的向量,让构造函数根据模板参数'rank'验证它。
NDimensionalArray matrix(std::vector<int> matrixDimensions)
{
if (matrixDimensions.size() != rank)
{
throw SomeException();
}
...
}
我认为任何编译器技巧都不能成为替代方案。 (除了使用宏的perhps,如果你能想到某些东西,尽管严格来说这不是编译技巧。)
不是直接的答案,但看看闪电战库。
你可以采用std :: tr1 :: array。 嗯:
#include <array>
template< class valType, int rank >
class NDimensionalArray
{
public:
NDimensionalArray(const std::tr1::array<rank>& dims);
// ...
};
NDimensionalArray<double,2> foo({10,10});
NDimensionalArray<double,2> bar({10}); // second dimension would be 0
NDimensionalArray<double,1> baz({10,10}); // compile error?
我真的不确定这是否有效! 我会通过考虑来运行它。
编辑根据评论,看起来这种方法看起来更像:
std::tr1::array<2> dims = {10, 10};
NDimensionalArray<double,2> foo(dims);
目前在标准化的C ++中没有好办法。 在C ++ 0x中,您将能够使用模板参数包进行近似(我认为我的语法正确,但不确定requires
扩展):
template <class ValType, int Rank>
struct NDimensionalArray
{
template <class... Args>
requires std::SameType<Args, ValType>... && std::True<sizeof...(Args) == Rank>
NDimensionalArray(Args... values)
{
...
}
};
Boost有一个多数组库,它使用自定义对象来构造它们的多维数组。 这是一个非常好的方法; 我建议你学习(或者更好,使用)他们的代码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.