-1

I have a class B that is supposed to contain a private std::array<A*>, and the size will be sent in through the constructor.

class B
{
  public:
    B(size_t s) : vv(s,nullptr), aa(s) {}
    // ... more stuff
  private:
    std::vector<A*>   vv;   // vector works fine
    std::array<A*,??> aa;   // but how to initialize an array??
}

This works fine with using std::vector, but it seems I cannot get it to work with std::array.

Adding another member const size_t ss and using it in the std::array declaration doesn't work either, even if it is a static const size_t ss - the compiler (VS2019 16.1.5, set to C++17) claims "...expected compile-time constant..."

class B  // another try with a static const size_t
{
  public:
    B(size_t s) : ss(s), aa(s) {}
    // ... more stuff
  private:
    static const size_t ss;
    std::array<A*,ss> aa;   // no, ...expected compile-time constant...
}

That message seems to imply there is no way - if the size needs to be known at compile time, it needs to be the same for all instances/objects of the class - which directly contradicts my plan.

Of course, I could make a template class, or I could simply stay with std::vector; or I could use a kind of 'PIMPL' (declare instead a pointer to that array, and create it with new in the constructor) - that's not the question.

The question is: Can I pass the size of the to-be array in the constructor, and directly create it from that?
Is there any fancy construct or trick?

[Note: not a duplicate of Initializing private std::array member in the constructor, or Initializing std::array private member through constructor, or How to construct std::array object with initializer list? - I don't want to pass values, but the size of the array]

Aganju
  • 6,295
  • 1
  • 12
  • 23
  • 1
    Why don't you want to use a vector? – Galik Jul 09 '19 at 02:08
  • 1
    The size of a `std::array` must be known and specified ***at compile-time***. What the constructor receives is not known until run time. You cannot use `std::array` in this manner, C++ simply does not work this way. – Sam Varshavchik Jul 09 '19 at 02:11
  • `vector` works fine, sure. I'd like to learn if I could use `array` in this context. I understand there is no or infinitesimal performance or memory gain - it's purely _educational_. – Aganju Jul 09 '19 at 02:12
  • 1
    Well, you just received the education that says that you cannot use `std::array` in this context. That's not what it's used for. – Sam Varshavchik Jul 09 '19 at 02:14
  • And thanks. It already became a lot clearer by simply _writing_ the question up - but after that effort I didn't want to throw it all away. It could help someone else too. – Aganju Jul 09 '19 at 02:19
  • You could try a template, or possibly maybe even a `constexpr`. But `constexpr` is a long shot. –  Jul 09 '19 at 02:32

2 Answers2

8

You can't. The size of std::array is determined at compile time, and not runtime. For runtime storage, use std::vector. The closest you can get to with a class, is to declare the class as a template, like so:

template<size_t size>
class Foo {
   std::array<size> member;
};

But if you want to pass the size as an arg to the constructor, you'll need to use std::vector.

robthebloke
  • 9,331
  • 9
  • 12
0

You can "pretend" to pass the size to the constructor.

template <size_t Size>
struct array_size_t {};

template <size_t Size>
constexpr array_size_t<Size> array_size {};

template <size_t Size>
class Foo {
public:
  explicit Foo(array_size_t<Size>) {}

private:
  std::array<int, Size> arr;
};

Foo foo{array_size<12>};

Not sure why you would want to use this code because Foo<12> foo; is much shorter than Foo foo{array_size<12>};.

Indiana Kernick
  • 5,041
  • 2
  • 20
  • 50