Home > Enterprise >  how to implement a class that supports both stack and heap allocations
how to implement a class that supports both stack and heap allocations

Time:04-12

What is the most straightforward way of forcing std::vector to use a stack-based buffer? My guess is to use std::pmr::vector.

I want to write a class in a way that enables the use of both the normal vector (which uses dynamic allocations) and also one which uses a custom buffer.

Here is a sample:

#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
#include <cstddef>
#include <memory_resource>

// how should I implement this class? Using a template? How?
struct Foo
{
    explicit Foo( const std::size_t count = 1000, const char fillChar = ' ' )
    : vec( count, fillChar )
    {
    }

    std::pmr::vector<char> vec; // I need both normal and pmr vector
                                // (depending on what the client chooses to use)
};


int main( )
{
    std::array<std::byte, 10'000> buffer;
    std::pmr::monotonic_buffer_resource rsrc { buffer.data( ), 10'000 };
    std::pmr::vector<char> vec( 6000, '*', &rsrc ); // this free vector is a sample that
                                                    // shows how I may want to allocate
                                                    // a buffer for the vector member of Foo
    // print the content for demonstration
    std::copy_n( std::begin( vec ), 5, std::ostream_iterator<char>( std::cout, " " ) );
    std::cout << '\n';


    // how should I achieve the above or something similar for this object
    Foo foo { 2000, '!' };
}

I would also want to mention that the aim is simplicity so I'll be glad to see a fairly simple approach. But any suggestion is welcome.

CodePudding user response:

One way could be to mimic the setup used by vector and the alias template pmr::vector:

namespace foo {
  template <class Allocator = std::allocator<char>>
  struct Foo {
      using size_type = typename std::vector<char, Allocator>::size_type;

      constexpr Foo(size_type count, const char value,
                    const Allocator& alloc = Allocator())
          : vec(count, value, alloc) {}

      std::vector<char, Allocator> vec;
  };

  namespace pmr {
    using Foo = foo::Foo<std::pmr::polymorphic_allocator<char>>;
  }
}  // namespace foo

Using foo::Foo and foo::pmr::Foo:

int main() {
    foo::Foo x(1000, '^');

    std::array<std::byte, 10'000> buffer;
    std::pmr::monotonic_buffer_resource rsrc{buffer.data(), buffer.size()};   
    foo::pmr::Foo y(2000, '$', &rsrc);
}

Demo

  • Related