Date: Wed, 2 Sep 2020 17:10:50 -0400

On Wed, Sep 2, 2020 at 2:46 PM Steve Hearnden via Std-Proposals <

std-proposals_at_[hidden]> 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

std-proposals_at_[hidden]> 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

Received on 2020-09-02 16:14:31