我需要一个在编译时已知大小的数组。我知道我可以使用 std :: vector 或 boost :: array 。但这并没有教我如何在内部工作。除了使用初始化程序之外,我还找不到如何将项添加到 boost :: array 中。我为通用数组编写了以下代码。我的目的是熟悉迭代器,模板特化等。以下是代码
template<typename T>
struct iterator_traits
{
typedef T value_type;
typedef T& reference_type;
typedef T* iterator;
typedef const T* const_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
};
template<typename T>
struct iterator_traits<T*>
{
typedef T* value_type;
typedef T*& reference_type;
typedef T** iterator;
typedef const T const_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
};
template<typename T, size_t size = 10>
class Array
{
public:
typedef typename iterator_traits<T>::value_type value_type;
typedef typename iterator_traits<T>::reference_type reference_type;
typedef typename iterator_traits<T>::iterator iterator;
typedef typename iterator_traits<T>::const_iterator const_iterator;
typedef typename iterator_traits<T>::reverse_iterator reverse_iterator;
Array() : lastIndex(0) {
}
void add(value_type element) {
if(lastIndex >= size)
throw std::out_of_range("Array is full");
array_[lastIndex++] = element;
}
reference_type at(unsigned int index){
if(index < size)
return array_[index];
else
throw std::out_of_range("Invalid index");
}
size_t capacity(){
return size;
}
iterator begin(){
return array_;
}
iterator end(){
return array_ + size;
}
const_iterator begin() const{
return array_;
}
const_iterator end() const{
return array_ + size;
}
reverse_iterator rbegin() {
return reverse_iterator(end());
}
reverse_iterator rend() {
return reverse_iterator(begin());
}
private:
value_type array_[size];
unsigned int lastIndex;
};
以上代码效果很好。以下是我的问题
1 - 如何像 boost :: array 那样创建我的数组呢?像
这样的东西Array<int> ints = { 10, 12 };
2 - 代码中是否有任何陷阱?
3 - 我必须对特征中的指针类型使用特化。这是最好的做法吗?
4 - 迭代器模式是否正确实现?
任何想法都会很棒!
答案 0 :(得分:2)
boost :: array使用该语言的一个特性:没有构造函数的struct可以使用初始化列表。如果您提供自己的构造函数,则无法使用初始化列表。
此外,您使用iterator_traits
错误。你的代码应该是
// type definitions
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;
iterator_traits用于迭代器的特征。此外,您可以只使用指针作为迭代器。 STL明确允许这样做。
答案 1 :(得分:2)
1 - 如何像boost :: array一样创建我的数组?像
这样的东西Array<int> ints = { 10, 12 };
在c ++中,如果struct,union或c-style数组符合聚合条件,则只能(当前)使用大括号括起初始化列表。要做到这一点,根据标准:
8.5.1.1聚合是一个数组或类(第9条),没有用户提供的构造函数(12.1),没有私有或受保护的非静态数据成员(第11条),没有基类(第10条),并且没有虚函数(10.3)。
如果您想在当前标准中使用它们,则必须使您的类具有这些功能。下一个标准(参见here)包括允许其他类型这样做的规定。
2 - 代码中是否有任何陷阱?
这是一个:你不能将东西添加到提升列表的原因是它总是具有相同数量的元素(分配的大小)。在您的阵列中,您可以添加元素,但在构造期间,您仍然在引擎盖下构建了10个元素。如果用户不期望默认构造函数被调用10次,这可能会导致一些令人惊讶的结果。
答案 2 :(得分:1)
2 - 有任何陷阱吗?
我会摆脱默认大小“size = 10”。 10是什么使得数组的默认大小?我所看到的恰恰是有人意外地忽略了它的大小,并假设它比它大。
关于添加元素和C风格的初始化,我不相信它可以做到这两点。它在boost中工作,因为(我相信)该对象非常简单,是一个数组。它无法动态重新调整大小。该类只是将迭代器(以及其他糖类,如:: at())添加到普通数组中。