Is g++ falsely throwing -Wnarrowing?

Viewed 300

This is GCC 7.4 running in C++14 mode:

        size_t i = 8;
        std::string strIndent { i, ' ' };

Looks fine, but I get back the warning:

AnalyticsDBI.cpp:538:48: warning: narrowing conversion of ‘i’ from ‘size_t {aka long unsigned int}’ to ‘char’ inside { } [-Wnarrowing]
                 std::string strIndent { i, ' ' };

This is a compiler bug? I can't understand how the compiler could select to wrong overload. Should be constructor 2, as shown here.

2 Answers

Compiling with clang shows that it's attempting to call the initializer_list<char> constructor in which size_t -> char is a narrowing conversion:

narrowing.cpp:5:26: error: non-constant-expression cannot be narrowed from type 'size_t' (aka 'unsigned long') to 'char' in initializer list [-Wc++11-narrowing]
        std::string strIndent { i, ' ' };
                                ^
narrowing.cpp:5:26: note: insert an explicit cast to silence this issue
        std::string strIndent { i, ' ' };
                                ^
                                static_cast<char>( )
1 error generated.

Using () instead will call the constructor you want:

 std::string strIndent(i, ' ');

Using braces prefers the list constructor (the one taking std::initializer_list<char> here, number 9 on cppreference). In this constructor, the elements are char, so it is a narrowing conversion. GCC will give you an actual error for this instead of only a warning if you compile with -pedantic-errors; this is not a conforming program because narrowing conversions are not allowed in braced initialization.

Related