c++compiler-errorsc++20stdarray

std::array couldn't be auto initialized for a certain data list


std::array couldn't be auto initialized for a certain data list:

    static constexpr auto k_strap4_function_setting = std::array{0xf0000000, 0x70000000};  // compile error
    static constexpr auto k_strap4_function_setting = std::array{0xe0000000, 0x70000000};  // compile error
    static constexpr auto k_strap4_function_setting = std::array{0xd0000000, 0x70000000};  // compile error
    static constexpr auto k_strap4_function_setting = std::array{0xc0000000, 0x70000000};  // compile error
    static constexpr auto k_strap4_function_setting = std::array{0xb0000000, 0x70000000};  // compile error
    static constexpr auto k_strap4_function_setting = std::array{0xa0000000, 0x70000000};  // compile error
    static constexpr auto k_strap4_function_setting = std::array{0x90000000, 0x70000000};  // compile error
    static constexpr auto k_strap4_function_setting = std::array{0x80000000, 0x70000000};  // compile error
    static constexpr auto k_strap4_function_setting = std::array{0x70000000, 0x70000000};  // good to work
    static constexpr auto k_strap4_function_setting = std::array{0x60000000, 0x70000000};  // good to work
    static constexpr auto k_strap4_function_setting = std::array{0x50000000, 0x70000000};  // good to work
    static constexpr auto k_strap4_function_setting = std::array{0x40000000, 0x70000000};  // good to work

here is the error log:

error: no viable constructor or deduction guide for deduction of template arguments of 'array'
    static constexpr auto k_strap4_function_setting = std::array{0xf0000000, 0x70000000};

The only difference is the highest bit is "1" for the "compile error" define.

Does that error make sense?
Or is a bug for std::array.


Solution

  • The type of a hexadecimal integer literal without any suffix is the first out of the following list that is able to represent the exact value of the literal:

    int
    unsigned int
    long
    unsigned long
    long long
    unsigned long long
    

    On a system with 32 bit wide int, the largest value representable by int is 0x7fffffff and the largest value representable by unsigned int is 0xffffffff. So all literals up to 0x7fffffff have type int and those from 0x80000000 to 0xffffffff have type unsigned int.

    The deduction guide for std::array is specified in such a way that it will fail if not all elements of the initializer have the same type. And that is why some of your examples fail.

    Either specify the element type of the array explicitly, e.g. std::array<unsigned int> instead of std::array, so that initializers with other types will be implicitly converted to the specified element type, or add U (or u) suffixes to your literals to force them always to choose only unsigned types from the list above.