模板n维数组的构造函数的规范 [英] Template Specifications for constructor of n-dimensional array

查看:103
本文介绍了模板n维数组的构造函数的规范的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在实现一个n维数组类,它是一个模板,如下所示(注意数据存储在一个线性数组中,其长度是所有维度的乘积):

  template< class valType,int rank> 
class NDimensionalArray
{
public:

private:
valType * m_data;
int * m_dimensions;
int m_rank;
};

所以这个想法是用户(我)可以指定一个2的数组,某些维度,即:

  NDimensionalArray< double,2>矩阵(10,10);现在的困难在于专门用于1-> n维的构造函数,每个构造函数都需要n个参数,其中n是数组的排名。现在我想到使用一个valarray like在printf()中使用,但是用这个定义一个具有2维的1维数组:

  NDimensionalArray< double,1>矩阵(10,10); 

是完全可以接受的行为。有没有一些巧妙的技巧,我可以使用让编译器做重复?实际上,只要我知道排名,并且每个维度的长度,构造函数可以是通用的:

  {
int nElements = m_dimensions [0];
for(int i = 1; i nElements * = m_dimensions [i];
m_data = new valType [nElements];
}

编辑:请注意,



此外,我考虑了一个构造函数的选项,如下所示:

  NDimensionalArray(const NDimensionalArray< int,1& dimension); 

其中可以使用:

  NDimensionalArray< int,1> dimVec(2); //需要一维数组的规范。 
dimVec(0)= 10;
dimVec(1)= 10;
NDimensionalArray< double,2>矩阵(dimVec);

这将是一个可行的解决方案,但它的丑陋相比,我想要的使用。同样访问多维数组将会变得非常痛苦,并且非常慢地必须为每次访问构建维度向量。

解决方案

好吧,我玩了一会儿。这里有一些模板元编程hackery做的事情接近你想要的。它允许您指定所有维度内联,它不做任何动态内存分配或其他这样的事情。此外,使用一个好的C ++编译器(我用VC ++ / O2 选项测试),代码将完全内联,没有任何副本(事实上,整个NDimensionalArray构造函数在调用点)。它将在编译时完全类型检查,并且不会让你通过太少或太多的维度。它可以重用于索引器。这里:

 模板< 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&
{
}

value_pack< T,N + 1> operator()(const T& tail)const
{
return value_pack< T,N + 1&
}

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&
}
} const values;


template< class ValType,int Rank>
struct NDimensionalArray
{
NDimensionalArray(value_pack< ValType,Rank> values)
{
// ...
}
}


int main()
{
NDimensionalArray< int,3& a(值(1)(2)(3));
}


I am implementing an n-dimensional array class which is a template as follows (Note that the data is stored in a linear array whose length is the product of all the dimensions):

template< class valType, int rank >
class NDimensionalArray
{
public:

private:
    valType* m_data;
    int* m_dimensions;
    int m_rank;
};

So the idea is that a user (me) can specify an array of rank 2, and of a certain dimension, ie:

NDimensionalArray<double,2> matrix(10,10);

Now the difficulty is in specializing constructors for 1->n dimensions, each constructor takes n parameters where n is the rank of the array. Now I thought of using a valarray like is used in printf(), however with this defining a 1-dimensional array with 2 dimensions ie:

NDimensionalArray<double,1> matrix(10,10);

would be perfectly acceptable behavior. Is there some neat trick I can use to let the compiler do the repetition? Realistically so long as I know the rank, and have the length of each dimension the constructor can be generic:

{
    int nElements = m_dimensions[0];
    for ( int i=1 ; i<m_rank ; ++i )
        nElements *= m_dimensions[i];
    m_data = new valType[nElements];
}

Edit: Note that a similar operation will be needed for accessors.

Also I have considered the option of a constructor which looks like:

NDimensionalArray( const NDimensionalArray<int,1>& dimensions );

Which could be used like:

NDimensionalArray<int,1> dimVec(2); // Need a specification for 1-dimensional arrays.
dimVec(0) = 10;
dimVec(1) = 10;
NDimensionalArray<double,2> matrix(dimVec);

This would be a viable solution, but its ugly compared to the use I would like. Also accessing multi-dimensional arrays would become a serious pain, and seriously slow having to construct a dimension vector for each access.

解决方案

Okay, I've played with this for a while. Here's some template metaprogramming hackery that does something close to what you want. It lets you specify all dimensions inline, it doesn't do any dynamic memory allocation or other such things. In addition, with a good C++ compiler (I tested with VC++ /O2 option), the code will be fully inlined, with no copies done (in fact, for me it inlined the whole NDimensionalArray constructor at the point of the call). It will typecheck completely at compile-time, and won't let you pass too few or too many dimensions. And it can be reused for indexers. Here goes:

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

这篇关于模板n维数组的构造函数的规范的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆