Ниже не удается скомпилировать с clang35 -std=c++11
:
#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;
}
с ошибкой
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>( )
OTOH, он предупреждает о сужении и компиляции на 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>)
Имеет ли смысл какое-либо поведение? Цитирование из cppreference
Все конструкторы, которые принимают std:: initializer_list как единственный аргумент, или как первый аргумент, если остальные аргументы имеют значение по умолчанию значения, проверяются и сопоставляются разрешением перегрузки против единственный аргумент типа std:: initializer_list
Если предыдущий этап не дает соответствия, все конструкторы T участвовать в разрешении перегрузки против множества аргументов, которые состоит из элементов списка бит-init, с ограничением что допускаются только не суживающиеся преобразования. Если этот этап создает явный конструктор как наилучшее совпадение для copy-list-initialization, компиляция не выполняется (обратите внимание, в простой copy-initialization, явные конструкторы вообще не рассматриваются)
Поскольку сужение конверсий недопустимо, я ожидаю, что шаг разрешения перегрузки не будет соответствовать конструктору A(std::initializer_list<int>)
и вместо этого будет соответствовать A(int, double)
. Например, смена A(std::initializer_list<int>)
на A(std::initializer_list<std::string>)
компилируется как с clang35
, так и g++48
и печатает
A::A(int, double)
как ожидалось.