#include <iostream>
#include <string>
#include <initializer_list>
class A
{
public:
A(int, bool) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
A(int, double) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
A(std::initializer_list<int>) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};
int main()
{
A a1 = {1, 1.0};
return 0;
}
(Этот вопрос является продолжением этого а>.)
Вышеупомянутая программа не скомпилируется с clang35 -std=c++11
init.cpp:15:14: error: type 'double' cannot be narrowed to 'int' in initializer list [-Wc++11-narrowing]
A a1 = {1, 1.0};
^~~
init.cpp:15:14: note: insert an explicit cast to silence this issue
A a1 = {1, 1.0};
^~~
static_cast<int>( )
в то время как g++48 -std=c++11
выбирает вывод предупреждения для диагностики неправильно сформированного сужения
init.cpp: In function ‘int main()’:
init.cpp:15:17: warning: narrowing conversion of ‘1.0e+0’ from ‘double’ to ‘int’ inside { } [-Wnarrowing]
A a1 = {1, 1.0};
^
init.cpp:15:17: warning: narrowing conversion of ‘1.0e+0’ from ‘double’ to ‘int’ inside { } [-Wnarrowing]
и выдает результат
A::A(std::initializer_list<int>)
Мой вопрос в том, должна ли A::A(std::initializer_list<int>)
быть жизнеспособной перегрузкой. Ниже приведены стандартные цитаты, которые, я думаю, подразумевают, что перегрузка initializer_list
не должна быть жизнеспособной.
От 13.3.2 [over.match.viable]
Во-вторых, чтобы
F
была жизнеспособной функцией, для каждого аргумента должна существовать последовательность неявного преобразования, которая преобразует этот аргумент в соответствующий параметрF
.
От 4 [conv]
Выражение
e
может быть неявно преобразовано в типT
тогда и только тогда, когда объявлениеT t=e
; корректно, для некоторой придуманной временной переменнойt
.
От 8.5.1 [dcl.init.aggr]
Если предложение-инициализатор является выражением, и для преобразования выражения требуется сужающее преобразование, программа имеет неправильный формат.
Использование 8.5.1
и 4
, так как следующее неправильно сформировано
std::initializer_list<int> e = {1, 1.0};
{1, 1.0}
не может быть неявно преобразовано в std::initializer_list<int>
.
Используя цитату из 13.3.2
, не должно ли это означать, что A::A(std::initializer_list<int>)
не является жизнеспособной функцией при разрешении перегрузки для A a1 = {1, 1.0};
? Не найдя жизнеспособных конструкторов initializer_list
, не должен ли этот оператор выбрать A::A(int, double)
?
int t = 1.0;
? Это не агрегатная инициализация, не так ли? - person Columbo   schedule 21.01.20158.5.1
я не вставил всю стандартную цитату, но поскольку вы упомянули агрегатную инициализацию, я думаю, это достаточно ясно. - person Pradhan   schedule 21.01.2015