3656. Inconsistent bit operations returning a count

Section: 22.15.5 [bit.pow.two] Status: WP Submitter: Nicolai Josuttis Opened: 2021-12-30 Last modified: 2022-07-25 20:32:58 UTC

Priority: 3

View all issues with WP status.


Among the bit operations returning a count, bit_width() is the only one not returning an int.

This has the following consequences:

std::uint64_t b64 = 1;
b64 = std::rotr(b64, 1);
int count1 = std::popcount(b64);     // OK
int count2 = std::countl_zero(b64);  // OK
int count3 = std::bit_width(b64);    // OOPS

The last line may result in a warning such as:

Warning: conversion from long long unsigned to int may change value

You have to use a static_cast to avoid the warning.

Note that P0553R4 explicitly states the following design considerations, which I would also assume to apply to the later added functions from P0556R3:

The counting operations return "int" quantities, consistent with the rule "use an int unless you need something else". This choice does not reflect, in the type, the fact that counts are always non-negative.

[2022-01-30; Reflector poll]

Set priority to 3 after reflector poll. Eight votes for P0, but request LEWG confirmation before setting it to Tentatively Ready.

[2022-02-22 LEWG telecon; Status changed: LEWG → Open]

No objection to unanimous consent to send the proposed resolution for LWG3656 to LWG for C++23. The changes in P1956 changed the functions to be more counting than mathematical.

[2022-07-08; Reflector poll]

Set status to Tentatively Ready after ten votes in favour during reflector poll.

[2022-07-15; LWG telecon: move to Ready]

[2022-07-25 Approved at July 2022 virtual plenary. Status changed: Ready → WP.]

Proposed resolution:

This wording is relative to N4901.

  1. Modify 22.15.2 [bit.syn], header <bit> synopsis, as indicated:

    template<class T>
      constexpr Tint bit_width(T x) noexcept;
  2. Modify 22.15.5 [bit.pow.two], as indicated:

    template<class T>
      constexpr Tint bit_width(T x) noexcept;

    -11- Constraints: T is an unsigned integer type (6.8.2 [basic.fundamental]).

    -12- Returns: If x == 0, 0; otherwise one plus the base-2 logarithm of x, with any fractional part discarded.