2

In c++17 you can do

std::array a{ "one", "two", "three" };

and get a std::array<const char*, 3>. Awesome!

Because array member variables must have their size specified in the class declaration this is not usable as a class variable. I would like to create a class with one of these arbitrarily long initialization list initialized arrays and one or more constexpr methods. I would expect the only constructor to take the initialization list as an argument. Is there a way to do this?

9
  • 2
    std::array is usable as class field just fine. But if you need variable size array then you need std::vector Commented Oct 27, 2018 at 20:56
  • std::vercot is unsuitable due to compile-time initialization requirements. The array size would be fixed per instance, but may be different in different instances. Commented Oct 27, 2018 at 21:00
  • 1
    @MichaelSurette Oh, it's suitable alright. It has stood the test of time just fine. Commented Oct 27, 2018 at 21:01
  • If you know array size at compile time then what is the problem with using std::array? Commented Oct 27, 2018 at 21:01
  • I would like to have the size of the initialization list be the size of the array, removing the requirement to count the entries, which may be a source of errors, especially on updates. Commented Oct 27, 2018 at 21:04

1 Answer 1

6

You can use a class templated on the size of the array (and the element type if you want), that has a variadic constructor. Something like this:

template <typename T, std::size_t N>
struct custom_array {
    std::array<T, N> data;

    template <typename... Args>
    constexpr explicit custom_array(Args... args) : data{args...} {
    }
};

To be able to deduce N you also need a deduction guide like this:

template <typename... Args>
explicit custom_array(Args... args) -> custom_array<std::common_type_t<Args...>, sizeof...(Args)>;

You can find a complete example on Compiler Explorer.

Sign up to request clarification or add additional context in comments.

4 Comments

Thank you for this worthy effort, it does however still suffer from the same issue as std::array in that you have to declare the initialization list in the class definition. This necessitates a separate class for each instance. It is an improvement in that the methods can be integrated into the template. Definitely worth studying to see if I can get around this limitation.
So you want std::arrays of different sizes in the same non-template class? I'm afraid that's not possible.
I don't mind a template class, just not a whole new class for each initialization list. If what I'm looking for is not possible, then I am a bit disappointed, but it is what it is.
It's a new instantiation for each type-size combination, that's true. It's not possible because arrays of different sizes are entirely different types. What you could do is to put most of your logic in a non-template base class and use virtual member functions to abstract the size-dependent parts of the concrete classes away.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.