Title
`bit_size_of` overflow handling
Status
new
Section
[meta.reflection.layout]
Submitter
Jay Ghiron

Created on 2026-08-05.00:00:00 last changed 3 days ago

Messages

Date: 2026-08-08.11:09:25

Proposed resolution:

This wording is relative to N5054.

  1. Modify [meta.reflection.layout] as indicated:

    consteval size_t bit_size_of(info r);
    

    -?- Constant When:

    1. (?.1) — If `r` represents an unnamed bit-field or a non-static data member that is a bit-field with width W, when W is less than or equal to `SIZE_MAX`.

    2. (?.2) — Otherwise, if `r` represents a data member description (T, N, A, W, NUA, ANN) ([class.mem.general]) and W is not ⊥, when W is less than or equal to `SIZE_MAX`.

    3. (?.3) — Otherwise, when `size_of(r)` is less than or equal to `SIZE_MAX / CHAR_BIT`.

    -9- Returns:

    1. (9.1) — If `r` represents an unnamed bit-field or a non-static data member that is a bit-field with width W, then W.

    2. (9.2) — Otherwise, if `r` represents a data member description (T, N, A, W, NUA, ANN) ([class.mem.general]) and W is not ⊥, then W.

    3. (9.3) — Otherwise, `CHAR_BIT * size_of(r)`.

    -10- Throws: `meta::exception` unless all of the following conditions are met:

    1. (10.1) — `dealias(r)` is a reflection of a type, object, value, variable of non-reference type, non-static data member, unnamed bit-field, direct base class relationship, or data member description.

    2. (10.2) — If `dealias(r)` represents a type, then `is_complete_type(r)` is `true`.

Date: 2026-08-05.00:00:00

Consider the following program, assuming the `static_assert` succeeds:

#include<meta>
#include<print>
#include<climits>
#include<cstdint>

static_assert(CHAR_BIT == 8 && sizeof(long) == 8 && SIZE_WIDTH == 64);

int main()
{
  std::println("{}", bit_size_of(^^long[288230376151711744]));
}

If the implementation supports an array of this size then it appears that this should output zero, since the multiplication that `bit_size_of` is described as doing ([meta.reflection.layout]) will wrap around to zero. I do not think this is the intent, however. Additionally if the type of `0ZU + CHAR_BIT` is signed, then wraparound will not happen if the multiplication results in a value greater than std::numeric_limits<decltype(0ZU + CHAR_BIT)>::max().

The following proposed resolution is what GCC currently implements, Clang does not even allow constructing a type large enough to trigger this situation. In the extremely absurd situation CHAR_BIT > SIZE_MAX this would forbid any uses with an object type. Perhaps there should be additional wording to ensure that calls which result in an exception being thrown are still considered constant.

History
Date User Action Args
2026-08-08 11:09:25adminsetmessages: + msg16551
2026-08-05 00:00:00admincreate