stx::builtin_array<T>
‘builtin_array’について
STLが提供するアルゴリズムや関数オブジェクトはvectorやlistに対してだけでなく、char[]やint[]などのビルトイン配列に対しても適用できるように作られています。
しかしながらビルトイン配列をSTLに適用させるときは、たとえば、
// int data[N]の中から1を探す
int data[N];
int* iter = std::find(data, data+N, 1);
if ( iter != data+N ) {
// found!!
}
のように記述することになります。これをSTLコンテナと同様、
// vector<int> dataの中から1を探す
vector<int> data;
vector<int>::iterator iter = std::find(data.begin(), data,end(), 1);
if ( iter != data.end() ) {
// found!!
}
のように記述できるよう、ビルトイン配列をwrapする’builtin_array’を作りました。要素のアクセスに関する基本操作だけでなく、要素の反転アクセスのためのreverse_iterator/const_reverse_iteratorをサポートしています。
また、builtin_arrayの比較演算(==, !=, < <=, >, >=)を用意しました。したがってbuiltin_arrayはinsertやeraseなどの要素の挿入/削除に関する操作を持たないことを除いて、vectorと同じ操作ができます。
‘builtin_array’を使えば、前述のコードは以下のように記述できます。
// int data[N]の中から1を探す
int data[N];
stx::builtin_array<int> ba(data,N);
stx::builtin_array<int>::iterator iter = std::find(ba.begin(), ba.end(), 1);
if ( iter != ba.end() ) {
// found!!
}
ソースコード
/*
* builtin_array for VC++6
*/
#include <iterator>
#include <algorithm>
#include <stdexcept>
namespace stx {
template<class T>
class builtin_array {
T* first_;
T* last_;
size_t size_;
// no-definition to prevent copy
builtin_array();
builtin_array(const builtin_array&);
builtin_array& operator=(const builtin_array&);
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T* iterator;
typedef const T* const_iterator;
typedef std::reverse_iterator<iterator,T> reverse_iterator;
typedef std::reverse_iterator<const_iterator,T> const_reverse_iterator;
builtin_array(T* first, T* last)
: first_(first), last_(last), size_(last-first) {}
builtin_array(T* first, size_t size)
: first_(first), last_(first+size), size_(size) {}
iterator begin()
{ return first_; }
const_iterator begin() const
{ return first_; }
iterator end()
{ return last_; }
const_iterator end() const
{ return last_; }
reverse_iterator rbegin()
{ return reverse_iterator(last_); }
const_reverse_iterator rbegin() const
{ return const_reverse_iterator(last_); }
reverse_iterator rend()
{ return reverse_iterator(first_); }
const_reverse_iterator rend() const
{ return const_reverse_iterator(first_); }
size_type size() const
{ return size_; }
size_type max_size() const
{ return size_; }
size_type capacity() const
{ return size_; }
bool empty() const
{ return size_ == 0; }
reference operator[](size_type n)
{ return *(first_+n); }
const_reference operator[](size_type n) const
{ return *(first_+n); }
reference at(size_type n)
{ if ( size_ <= n ) _Xran(); return *(first_+n); }
const_reference at(size_type n) const
{ if ( size_ <= n ) _Xran(); return *(first_+n); }
reference front()
{ return *first_; }
const_reference front() const
{ return *first_; }
reference back()
{ return *(last_-1); }
const_reference back() const
{ return *(last_-1); }
pointer body()
{ return first_; }
const_pointer body() const
{ return first_; }
std::pair<pointer,size_type> data()
{ return std::pair<pointer,size_type>(first_,size_); }
std::pair<const_pointer,size_type> data() const
{ return std::pair<const_pointer,size_type>(first_,size_); }
void swap(builtin_array& x) {
std::swap(first_, x.first_);
std::swap(last_, x.last_);
std::swap(size_, x.size_);
}
friend void swap(builtin_array& x, builtin_array& y)
{ x.swap(y); }
// internal use internary
bool _Eq(const builtin_array& x) const
{ return size() == x.size() && std::equal(begin(), end(), x.begin()); }
bool _Lt(const builtin_array& _X) const
{ return std::lexicographical_compare(begin(), end(), x.begin(), x.end()); }
private:
void _Xran () const
{ throw std::out_of_range("invalid builtin_array<T> subscript"); }
};
template<class T> inline
bool operator==(const builtin_array<T>& x, const builtin_array<T>& y)
{ return x._Eq(y); }
template<class T> inline
bool operator!=(const builtin_array<T>& x, const builtin_array<T>& y)
{ return !(_X == _Y); }
template<class T> inline
bool operator<(const builtin_array<T>& x, const builtin_array<T>& y)
{ return x._Lt(y); }
template<class T> inline
bool operator>(const builtin_array<T>& x, const builtin_array<T>& y)
{ return y < x; }
template<class T> inline
bool operator<=(const builtin_array<T>& x, const builtin_array<T>& y)
{ return !(y < x); }
template<class T> inline
bool operator>=(const builtin_array<T>& x, const builtin_array<T>& y)
{ return !(x < y); }
}
コンストラクタ
builtin_array(T* first, T* last) builtin_array(T* first, size_t size)
ビルトイン配列 first からbuiltin_arrayを構築します。
// sample int data[N]; builtin_array<int> ba(data,data+N); // または ba(data,N) int n = ba.size(); // n = N
※安全を期するため、デフォルトコンストラクタ/コピーコンストラクタ/コピー演算子はprivate部に宣言することで使えなくしてあります。
イテレータ
iterator begin(); const_iterator begin() const;
最初の要素を指すイテレータを返します。
iterator end(); const_iterator end() const;
最後の要素の直後を指すイテレータを返します。
// sample : 全要素をプリント
int data[N];
stx::builtin_array<int> ba(data,N);
stx::builtin_array<int>::iterator iter = ba.begin();
while ( iter != ba.end() ) {
cout << *iter << endl;
++iter;
}
reverse_iterator rbegin(); const_reverse_iterator rbegin() const;
最後の要素の直後を指す反転イテレータを返します。
reverse_iterator rend(); const_reverse_iterator rend() const;
最初の要素を指す反転イテレータを返します。
// sample : 全要素を逆順にプリント
int data[N];
stx::builtin_array<int> ba(data,N);
stx::builtin_array<int>::reverse_iterator iter = ba.rbegin();
while ( iter != ba.rend() ) {
cout << *iter << endl;
++iter;
}
empty / size / max_size
bool empty() const;
要素数が 0 なら true を返します。
size_type size() const; size_type max_size() const; size_type capacity() const;
いずれもコンストラクト時に設定した要素数を返します。
front / back / operator[] / at / data / swap
reference front() const_reference front() const
最初の要素を返します。
reference back() const_reference back() const
最後の要素を返します。
reference operator[](size_type n) const_reference operator[](size_type n) const
n番目の要素を返します。
reference at(size_type n) const_reference at(size_type n) const
n番目の要素を返します。n >= size() であるとき、out_of_range例外をthrowします。
std::pair<pointer,size_type> data() std::pair<const_pointer,size_type> data() const
配列のポインタと要素数(first()とsize())のpairを返します。
void swap(builtin_array& x)
*this と x の全要素を交換します。