我需要C ++数组类模板,该模板是固定大小的,基于堆栈的,并且不需要默认构造函数

StackOverflow https://stackoverflow.com/questions/3873625

因此,我一直在研究boost ::数组,但是确实需要定义默认的构造函数。我认为,用数据填充该数组的最佳方法是通过push_back(const t&)方法。根据构建配置,将其拨打多于大小(已知在编译时已知)会导致断言或异常。这样,它将始终包含有意义的数据。有人知道该概念的有效,便携式,可靠的实施吗?

有帮助吗?

解决方案

好吧,我本来以为有人现在会带来答案,但是似乎不是,所以走吧。

您想要的是我自己梦dream以求的东西: boost::optional_array<T,N>.

有两个变体:

  • 第一:类似 boost::array< boost::optional<T>, N >, ,这是每个元素可能会设置或可能不会设置。
  • 第二:类似于 std::vector<T> (不知何故),这都是设置的所有开始元素,所有以下元素都不是。

考虑到以前的问题 /评论,您似乎想要第二个,但这并不重要,因为两者都非常相似。

template <typename T, size_t N>
class stack_vector
{
public:
  bool empty() const { return mSize == 0; }
  size_t size() const { return mSize; }
  size_t capacity() const { return N; }
  size_t max_size() const { return N; }

  T& operator[](size_t i) { return *(this->pfront() + i); }
  /// ...

private:
  T* pfront() const { return reinterpret_cast<T*>(&mStorage); }

  std::aligned_storage< N * sizeof(T), alignof(T) > mStorage;
  size_t mSize; // indicate how many elements are set, from the beginning
};

让我们专注于那些非常特殊的操作:

template <typename T, size_t N>
void push_back(T const& t)
{
  new (this->pfront() + mSize) T(t); // in place construction
  ++mSize;
}

template <typename T, size_t N>
void clear()
{
  for (size_t i = 0; i != mSize; ++i)
  {
    (this->pfront() + i)->~T();
  }
  mSize = 0;
}

您可以注意到,主要困难是记住:

  • 如果在那里尚未构建元素,则需要安置新的 +复制构造而不是分配。
  • 应该正确处理变为“过时”的元素(即将在最后一个元素之后)(即调用其破坏者)。

传统的STL容器有许多操作可能很难实施。在 vector, ,元素改组(由于 insert 或者 erase)也许是最令人震惊的例子。

另请注意,使用C ++ 0x和Initializer-Lists vector 得到 emplace_back 直接构建元素,从而提起 CopyConstructible 要求,可能是您案件的一个很好的福音。

其他提示

boost::array<T, 12> ta;T[12] ta;;如果您不使用初始化列表,则将默认构建元素。

常见的解决方法是 boost::array<T*, 12> ta; 或许 boost::array<unique_ptr<T>, 12> ta;.

按值存储的唯一方法是复制,无法解决...这是初始化器列表所做的:

struct A {
    A(int i):_i(i){ cout << "A(int)" << endl; }
    A(const A& a){ cout << "A(const A&)" << endl; }
    ~A(){ cout << "~A()" << endl; }

    int _i;
};

int main(){
    boost::array<A, 2> ta = {{1, 2}};
}

这输出:

A(int)
A(const A&)
A(int)
A(const A&)
~A()
~A()
~A()
~A()

http://codepad.org/vjgeqwk5

在您的Boost ::数组中可能会存储Boost ::变体?使第一个参数为int或其他。

IE

boost::array<boost::variant<int, foo>, 6> bar;

好的,您必须处理一个变体,但分配了堆栈...

在C ++ 0x中,您得到了 std::array<type, size> (可能与boost ::数组相同)。您可以使用 fill() 或者 std::fill_n():

std::array<int, 30> array;
array.fill(0);
boost::array<int, 30> barray;
std::fill_n(barray.begin(), 30, 0);

如果要在定义上获得默认限制化,则可以使用Copy-CTOR:

static std::array<int, 30> const nullarray = {0, 0, 0, ..., 0}; // nullarray.fill(0);
// (...)
std::array<int, 30> array{nullarray};

为什么必须居住在堆栈上?您是否有经验证据表明创建和 reservea vector 太慢了(使用 vector 似乎是明显的答案)?

即使是,您也可以创建一个保留空间的向量池,并且 swap 预先分配的向量之一成本地副本。当您完成本地元素时,请再次将其交换(很像 splice 技巧 listS)。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top