Search code examples
c++c++11unsignednarrowing

What causes this code to trigger implicit int narrowing?


The following code makes clang to fail when -Wc++11-narrowing is specified

#include <stdint.h>

extern uint8_t numbers[];
extern int n;

uint8_t test(int num) {
    uint8_t a{n > 0 ? *numbers : 2};
    return a;
}

(Same code in godbolt: https://godbolt.org/z/nTKqT7WGd)

8:15: error: non-constant-expression cannot be narrowed from type 'int' to 'uint8_t' (aka 'unsigned char') in initializer list [-Wc++11-narrowing]
    uint8_t a{n > 0 ? *numbers : 2};

I read the standard and related issues but I cannot comprehend why a ternary operation with two results that are uint8_t or can be transparently narroweduint8_t (i.e: constant 2) result in a promotion to int that then wants to be explicitly narrowed.

Can someone explain why this happens? Thanks!


Solution

  • The second operand to the conditional expression has type uint8_t. The third operand, the literal 2, has type int.

    When the second and third operands to a conditional expression are of different arithmetic type, the usual arithmetic conversions are performed in order to bring them to their common type. [expr.cond]/7.2

    In this case the usual arithmetic conversions involve the promotion of both types, namely uint8_t and int. [expr.arith.conv]/1.5

    Because int can represent all values of type uint8_t, the result of the promotion of uint8_t is int. int is unaffected by integral promotions and remains int. [conv.prom]

    The result of the conditional expression has type int. A conversion from int to uint8_t is narrowing, since uint8_t cannot represent all values of type int.