Nano Hash - криптовалюты, майнинг, программирование

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

Проект стандарта C ++ (N3337) описывает преобразование указателей следующим образом:

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

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

и

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

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

Исходя из вышеизложенного, вполне нормально преобразовать указатель функции или указатель на 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*)
28.08.2014

  • Любой указатель на объект можно преобразовать в void* и обратно. Например, указатель на функцию может иметь совершенно другой размер, поэтому преобразование не будет (гарантировано) действительным. Но вы хотите иметь возможность проверить, равно ли оно нулю. (Обратите внимание, что POSIX действительно требует, чтобы вы могли преобразовать указатель функции в / из void*). 28.08.2014
  • Указатель на указатель не может быть преобразован в void *, что, на мой взгляд, глупо, поскольку он должен быть указателем на что-либо (это тип данных), а указатель - это тип данных. Но это отдельная тема. 28.08.2014
  • @CashCow Указатель на указатель можно преобразовать в void *. 28.08.2014
  • @CashCow, Возможно вы имели ввиду конвертацию в void **. Это запрещено. 28.08.2014
  • Это не дубликат моего вопроса. Мой вопрос касается iostreams и перегрузок operator<<, которые он предоставляет, а не о правилах неявного преобразования. 28.08.2014
  • Нет, я хочу аннулировать *, что должно быть разрешено, но не разрешено. Или нет хотя бы одного компилятора, о котором я знаю, возможно, Microsoft, и это могло быть исправлено. 29.08.2014

Ответы:


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) или < br> - последовательность преобразования многоточия (13.3.3.1.3).

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

1 Таблица 12 суммирует преобразования, определенные в разделе 4, и разбивает их на четыре непересекающиеся категории: преобразование Lvalue, корректировка квалификации, продвижение и преобразование. [Примечание: эти категории ортогональны по отношению к категории значения, cv-квалификации и представлению данных: преобразования Lvalue не изменяют cv-квалификацию или представление данных типа; Квалификационные корректировки не изменяют категорию значения или представление данных типа; а «Акции» и «Конверсии» не изменяют категорию значения или CV-квалификацию типа. - конец примечания]

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

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

Таблица стандартных преобразований, их категории и ранги

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

Глядя на / 4, мы видим:

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

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

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

28.08.2014
  • @RSahu, нет проблем! Если вам нужно более подробное объяснение, в котором вы могли бы найти что-нибудь полезное по пути, я более подробно остановился на том, как я добрался до этой цитаты. 28.08.2014
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

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

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..