Is it possible to exclude static_cast in the list of initializers?

In my code base, I often initialize an array or vector if bytes use the following syntax:

uint16_t foo = 0xAB, bar = 0xCD

// bytes = { 0xA, 0xB, 0xC, 0xD }
std::array<uint8_t, 4> bytes = {{
    foo >> 8,
    foo & 0x00FF,
    bar >> 8,
    bar & 0x00FF
}};

I get the following error from clang ++:

error: non-constant-expression cannot
 be narrowed from type 'int' to 'value_type' (aka 'unsigned char') in initializer list [-Wc++11-narrowing]
                        foo >> 8,
                        ^~~~~~~~~~~~~

The compiler will prompt me to add static_cast to disable this error. I know casting will work, but I wonder if casting can be avoided and the syntax can be kept as elegant as it is?

Thank you for your help.

+6
source share
3 answers

There is no elegant way out of this.

. foo >> 8 & c. int, . , .

+3

, static_cast , :

template <class ... Ts>
std::array<uint8_t, sizeof...(Ts)> make_char_array(Ts && ... ts) {
    return {{static_cast<uint8_t>(ts)...}};
}

auto bytes = make_char_array(...) , .

+4

:

constepxr uint8_t low_byte(uint16_t n) { return n & 0x00FF; }
constepxr uint8_t high_byte(uint16_t n) { return (n >> 8) & 0x00FF; }

uint16_t foo = 0x0A0B, bar = 0x0C0D;

// bytes = { 0x0A, 0x0B, 0x0C, 0x0D }
std::array<uint8_t, 4> bytes = {{ high_byte(foo),
                                  low_byte(foo),
                                  high_byte(bar),
                                  low_byte(bar)
}};
+2

All Articles