Stéphane de Luca
Stéphane de Luca

Reputation: 13621

Cannot define aclass property array from brace-encasing initialiser in C++

This does not compile, I am obliged to set 3 within the [].

Is there a way to let the compiler computes the exact length of the array based on literals?

class Foo {
    const uint8_t commands[] = {
        0x90,
        0x91,
        0x92,

    };
}

Upvotes: 0

Views: 64

Answers (4)

armagedescu
armagedescu

Reputation: 2155

Generally speaking C++ compiler is able to compute the size automatically

int main()
{
    const uint8_t commands[] = {
        0x90,
        0x91,
        0x92,

    };
    cout<<"sizeof: "<< sizeof(commands);

    return 0;
}

But compiler can't deduce them for class members:

class Foo {
     uint8_t commands[];
};
class Foo1 {
     const uint8_t commands[];
};
class Foo2 {
     const uint8_t commands[] = ...;
};

As specified in cppreference: Members of array type cannot deduce their size from member initializers: enter image description here I suppose this is a special constraint for classes, as these are supposed to be shared via header files. And this can be a potential source of inconsistences between headers. Such inconsistences are binary incompatible, can't be detected at compile time, nor linking time. Such binary incompatibility can lead to incorrect, undefined behavior, and crashes, and usualy it leads to that. The cause is very difficult to diagnose. Doing it inside a function never breaks binary incompatibility, as it always gets recompiled and relinked.

Upvotes: 0

St&#233;phane de Luca
St&#233;phane de Luca

Reputation: 13621

Following up @Erel answer: I couldn't do an inline so I did the following:

foo.h:

class Foo {
    static const uint8_t commands[];
}

foo.cpp:


const uint8_t Foo::commands[] = {
    0x90,
    0x91,
    0x92,
};

void Foo::bar() {
    Serial.println("sizeof(commands) is ok: %d", sizeof(commands));
}

Upvotes: 1

long.kl
long.kl

Reputation: 680

compiler can deduce and know command's size. you don't need to pass command's size. from c++11 you can use constexpr with static to declare const inside a class

class Foo {
    constexpr static int commands[] = {
        0x90,
        0x91,
        0x92,
    };
};

https://godbolt.org/z/cnh4o37Pq

Upvotes: 1

Erel
Erel

Reputation: 739

Assuming you do not need one copy per object of that class (thus do not need it to be a real member), yes, make it static:

class Foo 
{
    static inline const uint8_t commands[] = {0x90, 0x91, 0x92};
};

Upvotes: 1

Related Questions