Flexible array as a class member
Asked Answered
P

2

5

GCC G++ 9

This code:

   class foo {
     int bar[] = {111, 123};
   };

produces an error about initializer for flexible array. But this one:

   class foo {
     int bar[2] = {111, 123};
   };

compiles as normal. Any workaround for not counting the values I put in?

Pedology answered 8/1, 2020 at 21:45 Comment(7)
Hint: std::vector. C++ needs to know the exact size of a structure in advance. You can't make it up as you go.Trappings
No, no workarounds. C++ just doesn't work this way.Hopfinger
std::vector suits well for my usecase as i tested. it supports [] notation and does not want me to specify array size. i was aware of it, just i was not prepared that flexible array would be of a problem. thanks!!! :)Pedology
There is no such thing as flexible array member in C++Osbourne
@Osbourne Doesn't static constexpr int bar[] = {111, 123}; count as a flexible array member? It's probably unusable for OP, but still.Lorrainelorrayne
@Trappings There is no boost library on an Arduino. Sometimes libraries can't replace missing language features.Companionate
@Companionate This isn't Boost, it's in the C++ Standard Library. If that's not an option for reasons then that needs to be specified in the question as that's an edge case.Trappings
J
7

Unlike in a function where you can do

int foo[] = { 1, 2, 3 };

and the compiler will deduce the size of foo from the initializer, when you do

struct bar
{
    int foo[] = { 1, 2, 3 };
};

what you really have is

struct bar
{
    bar() : foo{ 1, 2, 3 } {}
    int foo[];
};

and that can't work because C++ does not allow flexible arrays like C does.

That leaves you with two options. The first is you specify the size. This isn't the greatest solution since it could introduce bugs but it will save you from dynamic initialization. The second option is to use a type that, at run time, can be initialized from the list. A std::vector for instance would fill that requirement nicely. Yes, there will be a dynamic memory allocation, but since std::vector is an RAII type, you don't need to worry about it and can use the default constructors and destructor.

June answered 8/1, 2020 at 21:55 Comment(4)
If a fixed size array is wanted, std::array<int,2> would be also appropriate.Bromine
@Pedology It's a great container. It's my go-to unless I can use a std::arrayJune
For std::array (without having to count the values) I guess something like static constexpr std::array init = {111, 123}; std::remove_const_t<decltype(init)> bar = init; could be an option.Lorrainelorrayne
Of course all the std::… solutions won't help if the target device is an Arduino where there is no boost library. Sometimes libraries can't make up for lack of language functionality.Companionate
F
1

By now the accepted answer is a bit out of date. Use a constexpr std::array. This has the added benefit you can also access it's size at a later time (without mucking around with "C" style sizeof)

#include <array>

struct bar
{
    static constexpr std::array foo{ 1, 2, 3 };
};


int main()
{
    return bar::foo.size();
}
Forspent answered 29/9 at 17:9 Comment(1)
noted, thanks for your inputPedology

© 2022 - 2024 — McMap. All rights reserved.