c++arraysconstructordefaultstack-based

I need C++ array class template, which is fixed-size, stack-based and doesn't require default constructor


So, I've been looking at boost::array but it does require default constructor defined. I think the best way of filling this array with data, would be through a push_back(const T&) method. Calling it more times than SIZE (known at compile-time) would result in assert or exception, depending on build configuration. This way it would always contain meaningful data. Does anyone know efficient, portable, reliable implementation of this concept?


Solution

  • Well, I would have thought that someone would have brought the answer now, however it seems not, so let's go.

    What you are wishing for is something I have myself dreamed of: a boost::optional_array<T,N>.

    There are two variants:

    Given the previous questions / comments, it seems you would like the second, but it doesn't really matter as both are quite alike.

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

    Let's focus on those very special operations:

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

    As you can notice, the main difficulty is to remember that:

    There are many operations on traditional STL container that may be tricky to implement. On a vector, element shuffling (due to insert or erase) are perhaps the most stricking examples.

    Also note that with C++0x and initializer-lists vector get emplace_back to directly construct an element in place, thus lifting the CopyConstructible requirement, might be a nice boon dependent on your case.