#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;
}
(Этот вопрос является продолжением до this.)Почему этот конструктор initializer_list является жизнеспособной перегрузкой?
выше программа не компилируется с 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)
?
Как применяется 8.5.1 для 'int t = 1.0;'? Это не агрегированная инициализация, не так ли? – Columbo
В сообщении было указано, что вы привязаны к тем конструкторам, которые принимают список инициализаторов, сильно одобрены. Таким образом, компилятор выбирает конструктор списка инициализаторов, а затем пытается преобразовать и поскольку он сужает компиляцию. – NathanOliver
@Columbo Извините, я не понял. Кроме того, для '8.5.1' я не вставлял всю стандартную цитату, но, поскольку вы упоминаете агрегатную инициализацию, я думаю, это достаточно ясно. – Pradhan