У меня есть устаревший код, который имеет следующие конструкторы.
CAgs (int ar, bool isReady);
CAgs (int ar, const char* options[][2] = NULL);
Он компилируется, но не будет ли это неоднозначным вызовом? Если я позвоню CAgs (10, 0);
какой конструктор будет вызываться?
Зависит ли это поведение от компилятора?
В северном направлении Я интерпретировал ваш вопрос как «почему это компилируется? Разве это не двусмысленно если бы я был называть это так?
Этот звонок является двусмысленный поскольку вызов каждого конструктора потребует неявного преобразования с CAgs (10, 0);
Цитировать некоторые источники:
§ 4.10.1 для const char* options[][2]
тип
Константа нулевого указателя является целочисленным литералом (2.14.2) со значением ноль
или значение типа std :: nullptr_t. Константа нулевого указателя может быть
преобразован в тип указателя; результатом является значение нулевого указателя
этот тип и отличается от любого другого значения объекта
указатель или тип указателя функции. Такое преобразование называется нулевым
преобразование указателя
4.12.1 для bool
тип
Значение арифметики, перечисление с незаданной областью, указатель или указатель на
тип члена может быть преобразован в значение типа bool. Нулевое значение,
значение нулевого указателя или значение указателя нулевого элемента преобразуется в
ложный; любое другое значение преобразуется в true.
Код наверняка компилируется, потому что параметры — это два разных и допустимых типа, и если вы передадите что-то, что не требует неоднозначного неявного преобразования, оно будет работать правильно. Но это не значит, что это не CAgs (10, 0);
В качестве небольшого несвязанного sidenote значение по умолчанию для указателя заставляет работать только следующее: CAgs (10);
, То же самое для любого другого ненулевого типа ( bool
конструктор будет выбран).
Вызов CAgs (10, 0);
неоднозначно, потому что int
0
является кандидатом на bool
а также указатель Ненулевой int
назвал бы CAgs (int ar, bool isReady);
Однако, потому что bool
это только кандидат в ненулевом случае.
И то и другое int
в bool
так же как 0
указатель является интегральное преобразование (4.7 [conv.integral]), так что оба преобразования имеют одинаковый порядок, что делает их неоднозначными. Это, однако, применяется только в том случае, если int
это так называемый константа нулевого указателя лайк NULL
или же 0
в противном случае int
преобразование указателя не является кандидатом, а int
в bool
один выбран.
Это неоднозначно. Для разрешения требуется явное приведение, например:
CAgs(4, (bool)0);
или же
CAgs(4, (char *)0);
Интегральные преобразования
Значение типа integer или перечисления с незаданной областью может быть
преобразован в любой другой целочисленный тип. Если преобразование указано в
неотъемлемые акции, это продвижение, а не конверсия.
- Если тип назначения не имеет знака, полученное значение является наименьшим значением без знака, равным исходному значению по модулю 2n.
где n — количество битов, используемых для представления типа назначения.- То есть, в зависимости от того, является ли тип назначения шире или уже, целые числа со знаком расширяются знаком [сноска 1] или усекаются, а целые числа без знака расширяются нулями или усекаются соответственно.
- Если тип назначения подписан, значение не изменяется, если исходное целое число может быть представлено в типе назначения. В противном случае результат определяется реализацией.
- Если тип источника — bool, значение false преобразуется в ноль, а значение true преобразуется в значение один из
тип назначения (обратите внимание, что если тип назначения int, это
это целочисленное продвижение, а не целочисленное преобразование)- Если тип назначения — bool, это логическое преобразование (см.
ниже)
…
Преобразование указателя
- Константа нулевого указателя (см. NULL) может быть преобразована в любой тип указателя, и результатом является значение нулевого указателя этого типа. Такое преобразование (известное как преобразование нулевого указателя) позволяет преобразовывать в квалифицированный cv тип как одно преобразование, то есть оно не считается комбинацией числовых и квалифицированных преобразований.
- Указатель prvalue на любой (необязательно cv-квалифицированный) тип объекта T может быть преобразован в указатель prvalue в (идентично cv-квалифицированному)
недействительным. Полученный указатель представляет в памяти тот же байт, что и
исходное значение указателя. Если исходный указатель нулевой
значение указателя, результатом является нулевое значение указателя
тип назначения.- Указатель prvalue на (необязательно cv-квалифицированный) тип производного класса может быть преобразован в prvalue-указатель на его доступный, однозначный (идентично cv-квалифицированный) базовый класс. Результатом преобразования является указатель на подобъект базового класса в указанном объекте. Значение нулевого указателя преобразуется в значение нулевого указателя
типа назначения.
…
Булевы преобразования
Значения целочисленного, с плавающей точкой, перечисление с незаданной областью, указатель,
и типы указателя на член могут быть преобразованы в значения типа bool.Нулевое значение (для целого, с плавающей запятой и с незаданной областью
перечисление) и нулевой указатель и нулевой указатель на член
значения становятся ложными. Все остальные ценности становятся правдой.Prvalue типа std :: nullptr_t, включая nullptr, может быть преобразовано в prvalue типа bool в контексте прямой инициализации (начиная с C ++ 14). Полученное значение ложно.
Источник: Неявные преобразования по совместительству
Поскольку оба они являются преобразованиями, они имеют одинаковый порядок, поэтому это должно быть неоднозначным. Но только в случае 0, потому что 0 можно преобразовать в NULL.