Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Narrowing conversion in pair with braced initializer compiling if second attribute is not braced-initialized

Tags:

c++

c++11

Since c++11, narrowing conversion is not allowed in list initialization (including aggregate initialization). So basically:

char c{1000}; // Does not compile with g++, clang, vc

But:

std::pair<char, double> p{1000, 1.0};

Compiles with all compiler?

But:

std::pair<char, double> p{1000, {1.0}};

Does not compile with VC (error C2398), gives a warning with clang and compiles silently with g++...

I would have expected VC behavior everywhere, i.e. a non-allowed narrowing conversion throwing an error. Which is compiler is right?


On the other hand, none of the variable declarations in the following snippets compile:

struct X {
    char c;
    double d;
};

X x1{999, 1.0};
X x2{999, {1.0}};

struct Y {
    char c;
    double d;
    Y (char c, double d) : c(c), d(d) { }
};

Y y1{999, 1.0};
Y y2{999, {1.0}};

So one of my guess may be that there is something special about std::pair? Something that would also narrowing braced-initialization?

like image 296
Holt Avatar asked Jun 20 '16 18:06

Holt


1 Answers

  1. std::pair<char, double> p{1000, 1.0}; is not diagnosed because it calls the template<class U1, class U2> pair(U1&&, U2&&) constructor (with U1 == int and U2 == double), which is an exact match; the narrowing doesn't happen until you get into the constructor body.

  2. std::pair<char, double> p{1000, {1.0}}; cannot call that constructor because the braced-init-list {1.0} is a non-deduced context, so you cannot deduce U2.

    • In clang/libc++, it calls the pair(const T1&, const T2&) constructor; however clang apparently doesn't consider the conversion needed to create a temporary for reference binding as part of the narrowing check. This is probably a bug.
    • GCC/libstdc++'s pair has a template<class U1> pair(U1&&, const T2&) constructor template, which is a better match. With this constructor, the second argument isn't narrowing, and the first argument is an exact match, so you get no error or warning.
like image 150
T.C. Avatar answered Oct 22 '22 16:10

T.C.