Ниже не может скомпилировать с clang35 -std=c++11
:Список инициализация и не разрешение перегрузки initializer_list конструктора
#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>()
Ото, он предупреждает о сужении и компилирует на 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
All constructors that take std::initializer_list as the only argument, or as the first argument if the remaining arguments have default values, are examined, and matched by overload resolution against a single argument of type std::initializer_list
If the previous stage does not produce a match, all constructors of T participate in overload resolution against the set of arguments that consists of the elements of the braced-init-list, with the restriction that only non-narrowing conversions are allowed. If this stage produces an explicit constructor as the best match for a copy-list-initialization, compilation fails (note, in simple copy-initialization, explicit constructors are not considered at all)
Поскольку сужение преобразования не допускаются, я бы ожидать, что шаг разрешение перегрузки не совпадать с 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)
, как и ожидалось.
Предположительно, вы имеете в виду Clang 3.5. То, что вы назвали двоичным, не очень полезно :) 'mv clang25 clang35'" oops " –
Вы правы :) Это соглашение об использовании версий, используемое командой, поддерживающей системы сборки на работе, и я никогда не думал об этом. – Pradhan