Подтвердить что ты не робот

Почему указатель на int преобразуется в void *, но указатель на функцию convert to bool?

В проекте С++ Draft Standard (N3337) приведено следующее о преобразовании указателей:

4.10 Преобразования указателей

2 rvalue типа "указатель на cv T", где T - тип объекта, может быть преобразован в rvalue типа "указатель на cv void". Результат преобразования "указатель на cv T" в "указатель на cv void" указывает на начало места хранения, где находится объект типа T, как если бы объект был наиболее производным объектом (1.8) типа T (т.е. Не подобъект базового класса).

и

4.12 Логические преобразования

1 Значение арифметики, перечисления, указателя или указателя на тип члена может быть преобразовано в rvalue типа bool. Значение нуля, значение нулевого указателя или значение указателя нулевого элемента преобразуется в значение false; любое другое значение преобразуется в true

Исходя из вышесказанного, вполне нормально преобразовать указатель на функцию или указатель на int в void*, а также bool.

Однако, учитывая выбор того и другого, который должен преобразовать указатель в?

И затем, почему указатель на функцию преобразуется в bool и указатель на int преобразуется в void*?

Программа:

#include <iostream>
using namespace std;

void foo(const void* ptr)
{
   std::cout << "In foo(void*)" << std::endl;
}

void foo(bool b)
{
   std::cout << "In foo(bool)" << std::endl;
}

void bar()
{
}

int main()
{
   int i = 0;
   foo(&bar);
   foo(&i);
   return 0;
}

Вывод, используя g++ 4.7.3:

In foo(bool)
In foo(void*)
4b9b3361

Ответ 1

Исходя из вышесказанного, вполне нормально преобразовать указатель на функцию или указатель на int в void*, а также bool.

В цитате указано, что указатель на объект можно преобразовать в cv void *. Функции не являются объектами, и это дисквалифицирует преобразование в cv void *, оставив только bool.


Однако, учитывая выбор того и другого, который должен преобразовать указатель в?

Он должен преобразовать в const void * через bool. Зачем? Хорошо, подготовьтесь к путешествию, которое начинается с разрешения перегрузки (§13.3 [over.match]/2). Акцент мой, конечно.

Но, как только функции кандидата и список аргументов были идентифицированы, выбор лучшей функции во всех случаях одинаковый:

- Во-первых, подмножество функций-кандидатов (те, которые имеют правильное количество аргументов и встречаются некоторые другие условия) выбирается для формирования набора жизнеспособных функций (13.3.2).

- тогда наилучшая жизнеспособная функция выбирается на основе неявных последовательностей преобразования (13.3.3.1), необходимых для сопоставления каждого аргумента с соответствующим параметром каждой жизнеспособной функции.

Как насчет этих неявных последовательностей преобразования?

Перейдем к §13.3.3.1 [over.best.ics]/3 и посмотрим, что такое неявная последовательность преобразования:

Хорошо сформированная неявная последовательность преобразования является одной из следующих форм:
- стандартная последовательность преобразования (13.3.3.1.1),
- пользовательская последовательность преобразования (13.3.3.1.2), или
- последовательность преобразования многоточия (13.3.3.1.3).

Нам интересны стандартные последовательности конверсий. Перейдем к стандартным последовательностям преобразования (§13.3.3.1.1 [over.ics.scs]):

1 Таблица 12 суммирует конверсии, определенные в разделе 4, и разбивает их на четыре непересекающиеся категории: Lvalue Transformation, Qualification Adjustment, Promotion, and Conversion. [Примечание. Эти категории ортогональны относительно категории значений, cv-квалификации и представления данных: Lvalue Transformations не изменяют cv-квалификацию или представление данных типа; Квалификационные корректировки не изменяют категорию значений или представление данных типа; а Promotions and Conversions не меняют категорию стоимости или cv-квалификацию типа. - конечная нота]

2 [Примечание. Как описано в разделе 4, стандартная последовательность преобразования является либо преобразованием Identity сама по себе (то есть без преобразования), либо состоит из одного-трех преобразований из четырех других категорий.

Важная часть находится в /2. Стандартной конверсионной последовательности допускается стандартное преобразование. Эти стандартные преобразования перечислены в таблице 12, показанной ниже. Обратите внимание, что и ваши конвертеры указателей, и булевские преобразования находятся там.

Table of standard conversions and their categories and ranks

Отсюда мы узнаем что-то важное: преобразования указателей и логические преобразования имеют одинаковый ранг. Помните, что, когда мы направляемся к ранжированию неявных последовательностей преобразования (§13.3.3.2 [over.ics.rank]).

Взглянув на /4, мы видим:

Стандартные последовательности преобразования упорядочены по их рангу: Точное совпадение - лучшее преобразование, чем Продвижение, которое является лучшим преобразованием, чем Конверсия. Две последовательности преобразований с одинаковым рангом неразличимы, если не применяется одно из следующих правил:

- преобразование, которое не конвертирует указатель, указатель на элемент или std:: nullptr_t для bool лучше, чем тот, который делает.

Мы нашли наш ответ в форме очень явного утверждения. Ура!