My proposal was intended to allow Arthur’s sample to be written as below.

 

template<class T, size_t Cap>

class fixed_capacity_vector {

    [[unconstructed]] T data_[ Cap];

    size_t size_ = 0;

public:

    size_t size() const { return size_; }

    T* data() { return data_; } // no cast necessary

    const T* data() const { return const_cast<const T*>(data_); }   // better cast - just a const_cast

    T& operator[](int i) { return data_[i]; }                                              // no need for data(), can access array directly

    const T& operator[](int i) const { return data_[i]; }                        // again access array directly.

    T& push_back(const T& value) {

        assert(size_ < Cap);

        T* p = ::new ((void*)&data[size_]) T(value);                                // not sure if the cast is needed here, don't need the function call.

        ++size_;

        return *p;

    }

    bool empty()

    {

        return (size_ == 0);

    }

    T& back()

    {

        return data_[size_ - 1];                                 // again, no need for function.

    }

    void pop_back() {

        back().~T();

        --size_;

    }

    fixed_capacity_vector()

        : size_(0)

    {}

    fixed_capacity_vector(const fixed_capacity_vector& rhs) {

        std::uninitialized_copy(rhs.begin(), rhs.end(), data_);

        size_ = rhs.size();

    }

    fixed_capacity_vector& operator=(const fixed_capacity_vector& rhs) {

        // left as an exercise for the reader

        // also, move semantics left as an exercise for the reader

    }

    ~fixed_capacity_vector() {

        while (!empty()) pop_back();

    }

};

 

Sent from Mail for Windows 10

 

From: Arthur O'Dwyer
Sent: 02 September 2020 22:11
To: Std-Proposals; Steve Hearnden
Subject: Re: [std-proposals] C++ create a class with array members which arenot constructed.

 

On Wed, Sep 2, 2020 at 2:46 PM Steve Hearnden via Std-Proposals <std-proposals@lists.isocpp.org> wrote:

I was looking at a performance issue, with some code and found that the cost of creating the dynamic heap memory was the significant cost.

 

It would have been handy to have a class which implemented something like std::vector, but with a *small* buffer of values  to use as an alternative piece of memory when the vector size was below a threshold. [...]

 

template< class T, size_t size>

class temp_vector

{

                [[unconstructed]] T _V[size];

                size_t m_constructed = 0;

public:

                ~temp_vector()

                {

///// Destroy the array manually.

                                for( size_t i = 0; i < m_constructed; i++ ){

                                                _V[i].~T();

}

}

}

 

I'm amazed that nobody has just given you teh codez yet. Here's basically what you should write:

 

template<class T, size_t Cap>

class fixed_capacity_vector {

    alignas(T) char data_[Cap * sizeof(T)];

    size_t size_ = 0;

public:

    size_t size() const { return size_; }

    T *data() { return (T*)data_; }

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

    T& operator[](int i) { return data()[i]; }

    const T& operator[](int i) const { return data()[i]; }

    T& push_back(const T& value) {

        assert(size_ < Cap);

        T *p = ::new ((void*)&data()[size_]) T(value);

        ++size_;

        return *p;

    }

    void pop_back() {

        back().~T();

        --size_;

    }

    fixed_capacity_vector(const fixed_capacity_vector& rhs) {

        std::uninitialized_copy(rhs.begin(), rhs.end(), data_);

        size_ = rhs.size();

    }

    fixed_capacity_vector& operator=(const fixed_capacity_vector& rhs) {

        // left as an exercise for the reader

        // also, move semantics left as an exercise for the reader

    }

    ~fixed_capacity_vector() {

        while (!empty()) pop_back();

    }

};

 

Notice the Rule of Three/Five here. If you provide a custom destructor, you should also provide custom copy and move operations (or =delete them).

 

This is also available fully fleshed out in Boost, in the form of boost::static_vector; and there is an active WG21 proposal, P0843, currently targeting the Library Fundamentals v3 TS.

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p0843r4.html

 

HTH,

Arthur