14

Is there a C++ type that acts like a "dynamically sized non resizable array"? This kind of type can be thought of as one of two things:

  • vector<T> but without resize, push_back, etc.
  • array<T,N> but where N is dynamic and not static.

I do not want a solution that only works if the type of the elements within the array is a non-copyable type. I want a generic solution.

nvoigt
  • 75,013
  • 26
  • 93
  • 142
tohava
  • 5,344
  • 1
  • 25
  • 47
  • Why do you need this? Why cant you use either an vector or an array? – 463035818_is_not_an_ai Mar 05 '15 at 12:52
  • 2
    I like my types to be as accurate as possible. I plan on using some `vector` but settings its size only once and then only changing its values. I prefer if I could document this via the type system instead of via a comment. – tohava Mar 05 '15 at 12:53
  • @Cyber - but I don't want it only for noncopyable value types, I want it for all types. – tohava Mar 05 '15 at 12:54
  • What's wrong with using `std::vector<>` and just not using `resize()`, `push_back`? Just because you're not going to use it doesn't mean you need it to be removed from the interface. It's pointless to look for a container that does exactly only the features you plan to use. – tenfour Mar 05 '15 at 13:01
  • 2
    Why would an array class work "only" if the types are non-copyable? – Neil Kirk Mar 05 '15 at 13:01
  • 2
    @tenfour: There's no way to prevent those functions from being used, if someone forgets that it's not supposed to be resized. That could be disastrous if you rely on stable iterators and references to elements. – Mike Seymour Mar 05 '15 at 13:02
  • As far as I know there was a proposal of `std::dynarray`. But now I do not see it in the C++ Working Draft. – Vlad from Moscow Mar 05 '15 at 12:53
  • 1
    @Cyber - This is not a duplicate. Note that in the original question the solution advises to use noncopyable elements and I specifically said I want a generic one. – tohava Mar 08 '15 at 09:46

1 Answers1

28

Yes, there (pretty much) is. std::unique_ptr<T[]>. The primary template has a partial specialisation for this case, which provides the appropriate interface (operator [], no operator * etc.)

Alternatively, you can wrap std::vector in your own class and restrict its interface. You could even do that by deriving a class from std::vector using non-public inheritance and publishing only the relevant parts of its interface:

template <class T, class A = std::allocator<T>>
struct FixedVector : private std::vector<T, A>
{
  using FixedVector::vector::vector;
  using FixedVector::vector::operator=;
  using FixedVector::vector::get_allocator;
  using FixedVector::vector::at;
  using FixedVector::vector::front;
  using FixedVector::vector::back;
  using FixedVector::vector::data;
  using FixedVector::vector::begin;
  using FixedVector::vector::cbegin;
  using FixedVector::vector::end;
  using FixedVector::vector::cend;
  using FixedVector::vector::empty;
  using FixedVector::vector::size;
  using FixedVector::vector::operator[];
};
Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455