Подтвердить что ты не робот

Сужение преобразования в паре с компиляцией с принудительным инициализатором, если второй атрибут не был скопирован-инициализирован

Так как С++ 11, сужение преобразования не разрешено в инициализации списка (включая агрегатную инициализацию), Итак, в основном:

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

Но:

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

Скомпилируется со всем компилятором?

Но:

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

Не компилируется с VC (ошибка C2398), дает предупреждение с clang и компилируется молча с g++...

Я бы ожидал поведения VC всюду, т.е. недопустимое сужение конверсии, забрасывающее ошибку. Какой компилятор прав?


С другой стороны, ни одна из объявлений переменных в следующих фрагментах не компилируется:

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}};

Итак, одно из моих предположений может заключаться в том, что есть что-то особенное в std::pair? Что-то, что также сузило бы инициализацию с привязкой?

4b9b3361

Ответ 1

  • std::pair<char, double> p{1000, 1.0}; не диагностируется, потому что он вызывает конструктор template<class U1, class U2> pair(U1&&, U2&&)U1 == int и U2 == double), который является точным совпадением; сужение не происходит, пока вы не попадете в тело конструктора.

  • std::pair<char, double> p{1000, {1.0}}; не может вызывать этот конструктор, потому что бит-init-list {1.0} является не выводимым контекстом, поэтому вы не можете вывести U2.