分享
 
 
 

cfc::array,一个多维数组类

王朝other·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

发信人: RoachCock (chen3feng), 信区: Programming

标 题: cfc::array,一个多维数组类

发信站: BBS 水木清华站 (Wed May 29 10:46:42 2002)

cfc::array

boost提供了boost::array,但是那只是一维的数组,我实现的这个支持一维,二维和三

维数组,三维以上的没有支持,我想你大概也不大会用到吧?:)

用标准STL容器vector来实现多维数组的话,空间是不连续的,用boost::array实现多维

数组的话,空间是连续的,但是boost的array没有基接口.

我提供的数组类同时支持我实现的这个支持一维,二维和三维数组,提供了所有数组的

基类array_base,一维数组的基类array_1d_base,二维数组的基类array_2d_base,三维数

组的基类array_3d_base,这就解决了C中多维数组的参数传递麻烦的问题.

该模板类实现了STL接口,可以像使用STL容器一样使用它.由于我对STL了解不过,实现的

也许不好,欢迎不吝斧正

同时实现了[]和()运算符,实现()运算符的原因是它再多为数组的情况下比[]要高效的

多.使用()的原因是受Basic语言的影响

对于每一维数组本身和基类的,我都提供了不同版本的实现,例如在基类array_2d_base

中,我用乘法实现(),而在array_2d中,我用原始数组的[]来实现,

这好像违背了不覆盖基类非虚函数的原则,其实不然,因为派生类中的重载做的是和基

类中完全一样的动作,但是却是优化的版本,而且基类的版本不算很低效,没必要用虚

函数,因为这样可能更慢而且不利于内联化.这样做的唯一原因就是为了效率.

还需要注意的是,由于MSVC模板实现的不好,有些特性还不适用,例如VC把模板中的数组

引用的定义视为错误,因为它把数组的大小看作0,而指针就没事,暂时还没解决

我还写了一个 dynamic_array<typename T,int dim=1>类,根据dim分别派生于

array_1d_base,array_2d_base,array_3d_base还没调试好,等好了,而且本文没有受

到大家唾弃的话在post吧.还有share_array...任重而道远,以后再说吧.

所有的类定义于namespace cfc,meams chen feng's class libraries.

你会在我的源代码中看到boost::function和boost::array的影子,感谢boost!

模板类的使用很简单:

#include "cfc\array.h"

using namespace cfc;

void foo(array_1d_base<int> & a)

{

a[0]+=10;

}

int main()

{

array<int ,10> a1;//一维数组

array<int ,10, 10> a2;//二维数组

array<int ,10, 10, 10> a3;//二维数组

a1[0]=10;

a1(0)=10; //Basic风格

a3[0](1,1)=10;

a3[0][0](0)=10;

foo(a1);

foo(a2[0]);

foo(a3[0][0]);

}

这是源程序:

使用了根据模板参数选择基类从而可以实例化生成有较大差别的类的手法, :)

////////////////////////////////////////////////////////////////////////////

////////////////////////////////

file://array.h ,array类和其的实现

#ifndef _ARRAY_H_

#define _ARRAY_H_

#ifdef _MSC_VER

#define CFC_STATIC_CONST(type, assign) enum{assign}

#else

#define static const type assign

#endif

#include "arrays.h"

namespace cfc

{

namespace detail

{

namespace array

{

template <int n>

struct real_get_impl

{

};

template <>

struct real_get_impl<1>

{

template<typename T, int d1, int d2, int d3>

struct dimensions

{

typedef array_1d<T, d1> type;

};

};

template <>

struct real_get_impl<2>

{

template <typename T, int d1, int d2, int d3

>

struct dimensions

{

typedef array_2d<T, d1, d2> type;

};

};

template <>

struct real_get_impl<3>

{

template <typename T, int d1, int d2, int d3

>

struct dimensions

{

typedef array_3d<T, d1, d2, d3> type

;

};

};

template <typename T, int d1, int d2, int d3>

struct get_impl

{

CFC_STATIC_CONST(int, value = int(d2!=-1)

+

int(d3!=-1)

+

1

);

typedef typename real_get_impl<value>::

template dimensions<T, d1, d2, d3>::

type type;

};

}

}

template <typename T, int d1, int d2 = -1, int d3 = -1>

class array : public detail::array::get_impl<T, d1, d2, d3>::type

{

typedef typename detail::array::

get_impl<T, d1, d2, d3>::type

base_type;

public:

array(){}

};

}

#endif file://_ARRAY_H_

////////////////////////////////////////////////////////////

// array_base.h

#ifndef _ARRAY_BASE_H_

#define _ARRAY_BASE_H_

#include <cstddef>

#include <iterator>

#include <algorithm>

#include <stdexcept>

namespace cfc

{

template <typename T>

class array_base

{

public:

typedef T value_type;

typedef T* iterator;

typedef const T* const_iterator;

typedef T& reference;

typedef const T& const_reference;

typedef /*std*/::size_t size_type;

typedef /*std*/::ptrdiff_t difference_type;

#ifdef _MSC_VER

typedef std::reverse_iterator<iterator,T> reverse_iterator;

typedef std::reverse_iterator<const_iterator,T> const_reverse_iterat

or;

#else

typedef std::reverse_iterator<iterator> reverse_iterator;

typedef std::reverse_iterator<const_iterator> const_reverse_iterator

;

#endif

public:

iterator begin() { return pdata; }

const_iterator begin() const { return pdata; }

iterator end() { return pdata + size(); }

const_iterator end() const { return pdata + size(); }

reverse_iterator rbegin() { return reverse_iterator(end()); }

const_reverse_iterator rbegin() const {

return const_reverse_iterator(end());

}

reverse_iterator rend() { return reverse_iterator(begin()); }

const_reverse_iterator rend() const {

return const_reverse_iterator(begin());

}

// at() with range check

reference at(size_type i) { rangecheck(i); return pdata[i]; }

const_reference at(size_type i) const { rangecheck(i); return elems[

i]; }

// front() and back()

reference front() { return pdata[0]; }

const_reference front() const { return pdata[0]; }

reference back() { return pdata[size()-1]; }

const_reference back() const { return pdata[size()-1]; }

// size is constant

bool empty() { return pdata != 0; }

size_type max_size() { return size(); }

// swap (note: linear complexity)

file://void swap (array<T,N>& y) {

// std::swap_ranges(begin(),end(),y.begin());

file://}

// direct access to data

const T* data() const { return pdata; }

size_type size() const

{

int sum=1;

for(int i=0;i<dim_count;i++)

sum*=dims[i];

return sum;

}

void assign (const T& value)

{

std::fill_n(begin(),size(),value);

}

void swap (array_base<T>& y)

{

if(size() != y.size())throw std::length_error("array

");

std::swap_ranges(begin(),end(),y.begin());

}

template <typename T2>

array_base<T>& operator= (const array_base<T2>& rhs)

{

std::copy(rhs.begin(),rhs.end(), begin());

return *this;

}

size_t get_dims(size_t index){return dims[i];}

void rangecheck (size_type i)

{

if (i >= size()) { throw std::range_error("array");

}

}

protected:

array_base(){}

protected:

T * pdata;

int dim_count;

int dims[3];

array_base(int d):dim_count(d){}

};

// comparisons

template<class T1,class T2>

bool operator== (const array_base<T1>& x, const array_base<T2>& y) {

return std::equal(x.begin(), x.end(), y.begin());

}

template<class T>

bool operator< (const array_base<T>& x, const array_base<T>& y) {

return std::lexicographical_compare(x.begin(),x.end(),y.begi

n(),,y.end());

}

template<class T1,class T2>

bool operator!= (const array_base<T1>& x, const array_base<T2>& y) {

return !(x==y);

}

template<class T1, class T2>

bool operator> (const array_base<T1>& x, const array_base<T2>& y) {

return y<x;

}

template<class T1, class T2>

bool operator<= (const array_base<T1>& x, const array_base<T2>& y) {

return !(y<x);

}

template<class T1, class T2>

bool operator>= (const array_base<T1>& x, const array_base<T2>& y) {

return !(x<y);

}

// global swap()

template<class T1, class T2>

inline void swap (array_base<T1>& x, array_base<T2>& y) {

x.swap(y);

}

template <typename T>

class array_1d_base:public array_base<T>

{

public:

const_reference operator [](size_type index)const

{

return pdata[index];

}

reference operator[](size_type index)

{

return pdata[index];

}

const_reference operator ()(size_type index)const

{

return pdata[index];

}

reference operator()(size_type index)

{

return pdata[index];

}

public:

array_1d_base(T* pd,size_type d1)

{

dim_count = 1;

pdata = pd;

dims[0] = d1;

}

protected:

array_1d_base() {dim_count=1;}

};

template <typename T>

class array_2d_base : public array_base<T>

{

public:

const array_1d_base<T> operator[](size_type index)const

{

return array_1d_base<T>(pdata+index*dims[1],dims[1])

;

}

array_1d_base<T> operator[](size_type index)

{

return array_1d_base<T>(pdata+index*dims[1],dims[1])

;

}

////////////////////////////////////////////////////////////

//

// Basic style access

const_reference operator ()(size_type index1, size_type inde

x2)cconst

{

return pdata[index1 * dims[1] + index2];

}

reference operator()(size_type index1, size_type index2)

{

return pdata[index1 * dims[1] + index2];

}

public:

array_2d_base(T *pd,size_type d1,size_type d2)

{

dim_count = 2;

pdata = pd;

dims[0] = d1;

dims[1] = d2;

}

protected:

array_2d_base() {dim_count = 2;}

};

template <typename T>

class array_3d_base : public array_base<T>

{

public:

const array_2d_base<T> operator[](size_type index)const

{

return array_2d_base<T>(

pdata + index * dims

[1] * dims[2],

dims[1],

dims[2]);

}

array_2d_base<T> operator[](size_type index)

{

return array_2d_base<T>(

pdata + index * dims

[1] * dims[2],

dims[1],

dims[2]

);

}

////////////////////////////////////////////////////////////

//

// Basic style access

/*

const_reference operator ()(

size_type index1,

size_type index2,

size_type index3)const

{

return pdata[

index1 * dims[1] *dims[2] +

index2 * dims[2] +

index3

];

}*/

reference operator()(

size_type index1,

size_type index2,

size_type index3)

{

return pdata[

index1 * dims[1] *dims[2] +

index2 * dims[2] +

index3

];

}

protected:

array_3d_base() {dim_count=3;}

};

}

#endif file://_ARRAY_BASE_H_

////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////

// arrays.h, array_1d,array_2d,array_3d的实现

#ifndef _ARRAYS_H_

#define _ARRAYS_H_

#include "array_base.h"

namespace cfc

{

template <typename T, int dim1>

class array_1d : public array_1d_base<T>

{

public:

CFC_STATIC_CONST(size_type, static_size = dim1);

const_reference operator[](size_type index)const

{

return data[index];

}

reference operator[](size_type index)

{

return data[index];

}

////////////////////////////////////////////////////////////

//

//

const_reference operator()(size_type index)const

{

return data[index];

}

reference operator()(size_type index)

{

return data[index];

}

protected:

array_1d()

{

pdata = &data[0];

dims[0] = dim1;

}

protected:

T data[dim1];

};

///////////////////////////////////////////////////////////////////

// 2d

template <typename T, int dim1, int dim2>

class array_2d : public array_2d_base<T>

{

#ifndef _MSC_VER file://MSC doesn't support ref to a template array

private:

typedef T (&index_type)[dim2];

typedef T const (&const_index_type)[dim2];

public:

const_index_type operator[](size_type index)const

{

return data[index];

}

index_type operator[](size_type index)

{

return data[index];

}

#endif

public:

CFC_STATIC_CONST(size_type, static_size = dim1 * dim2);

const_reference operator()(size_type index1, size_type index

2)coonst

{

return data[index1][index2];

}

reference operator()(size_type index1, size_type index2)

{

return data[index1][index2];

}

protected:

array_2d()

{

pdata = &data[0][0];

dims[0] = dim1;

dims[1] = dim2;

}

private:

T data[dim1][dim2];

};

///////////////////////////////////////////////////////////////////

// 3d

template <typename T, int dim1, int dim2, int dim3>

class array_3d : public array_3d_base<T>

{

#ifndef _MSC_VER

private:

typedef T (&index_type)[dim2][dim3];

typedef T const (&const_index_type)[dim2][dim3];

public:

const_index_type operator[](size_type index)const

{

return data[index];

}

index_type operator[](size_type index)

{

return data[index];

}

#endif

public:

CFC_STATIC_CONST(size_type, static_size = dim1 * dim2 * dim3

);

const_reference operator()(

size_type in

dex1

size_type in

dex2

size_type in

dex3

)const

{

return data[index1][index2][index2];

}

reference operator()(

size_type index1,

size_type index2,

size_type index3)

{

return data[index1][index2][index3];

}

protected:

array_3d()

{

pdata =&data[0][0][0];

dims[0] = dim1;

dims[1] = dim2;

dims[2] = dim3;

}

private:

T data[dim1][dim2][dim3];

};

}

#endif//_ARRAYS_H_

// the end.:)

--

namespace cfc

{

class dummy{};

};

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有