Почему разрешены разные функции преобразования для int и const int?

Почему следующее разрешено компилировать на C++?

#include<iostream>
using namespace std;

class mytest
{
public:    
    operator int()
    {
        return 10;
    }

    operator  const int()
    {
        return 5;
    }
};

int main()
{
    mytest mt;
    //int x = mt;    //ERROR ambigious 
    //const int x = mt; //ERROR ambigious
}

Почему имеет смысл разрешать компилировать разные версии (на основе постоянства) оператора преобразования, если их использование всегда приводит к неоднозначности?

Может кто-нибудь прояснить, что мне здесь не хватает?

Предположение: никто не позаботился о том, чтобы составить список слегка полезных и совершенно бесполезных случаев, поэтому в стандарте нет правила для этого. Например, создание const int() volatile может снова сделать его полезным. Возможно.

Bo Persson 20.06.2018 11:38

Нет правила против бесполезных заявлений. Пытаться исключить все бесполезные конструкции - очень плохая стратегия для языкового дизайна.

curiousguy 21.06.2018 02:24

@curiousguy Компилятор выдает ошибку для функций, различающихся только типом возвращаемого значения ... это просто частный случай этого сценария ... поэтому следует исключить ошибки

code707 22.06.2018 16:55

@ code707 По определению функции не могут отличаться только типом возвращаемого значения, и компилятор жалуется на два разных объявления та же функция.

curiousguy 09.12.2018 04:05
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
25
4
1 649
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Для преобразования они неоднозначны; но вы можете называть их явно. например

int x = mt.operator int();
const int x = mt.operator const int();

У вас есть идеи, в каких случаях это может иметь смысл?

Wolf 20.06.2018 11:27

В реальном мире я ничего не могу придумать.

songyuanyao 20.06.2018 11:28

Может быть, для привязки указателей на функции-члены? У меня нет под рукой синтаксиса ...

Wolf 20.06.2018 11:30

@Wolf Да, вы можете это сделать, но я все еще не думаю, что это подходящее использование функции преобразования.

songyuanyao 20.06.2018 11:33

Я думаю, что это следует запретить в стандарте

code707 20.06.2018 11:37

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

Useless 20.06.2018 11:51

why does it make sense to allow different version(based on constness) of conversion operator (to be compiled) when their use always result in ambiguity;

Обычно это не имеет смысла (кроме очень искусственных вариантов использования), и компилятор может вас об этом предупредить:

prog.cc:12:25: warning: type qualifiers ignored on function return type [-Wignored-qualifiers]
     operator  const int()
                         ^

Можете ли вы добавить такой вариант использования?

Wolf 20.06.2018 11:26

@Wolf См. Ответ songyuanyao. Вариант использования - продемонстрировать, что вы можете различить разницу, имея возможность вызывать их по отдельности. Вот почему я считаю это искусственным, бесполезным.

Jodocus 20.06.2018 11:28

И поскольку никто, скорее всего, этого не сделает (по очевидным причинам), не имеет смысла вносить изменение формулировки, которое запрещало бы это. Во всяком случае, это мои 2 цента.

StoryTeller - Unslander Monica 20.06.2018 11:32

Рассмотрим некоторый шаблонный код, в котором вместо int и const int напрямую вы получаете более сложное вычисление типов, которое, случается, выводит эти типы для некоторых аргументов шаблона.

T.C. 20.06.2018 11:35

@ T.C. Может быть, но пример code707 не вводит понятия шаблонов.

Jodocus 20.06.2018 11:40

Не совсем то же самое, но немного другая подпись: operator const int&() Имеет смысл; если это преобразование, которое, как вы знаете, может происходить часто, и хотите его кэшировать (ну, может быть, не int, а более крупный объект); и если его перемещение стоит дорого по неизвестной причине ... Впрочем, я не видел такого в реальном мире.

UKMonkey 20.06.2018 11:41
Ответ принят как подходящий

Я прихожу к выводу, что явно не разрешено писать операторы диалога, которые отличаются только постоянством их возвращаемого значения. Это слишком дорогой для явного запрета процесса компиляции.

Помните, что функции (члены), которые отличаются только своим возвращаемым типом

class mytest
{
    int f();
    const int f();
};

запрещены:

error: ‘const int mytest::f()’ cannot be overloaded

Просто операторы преобразования начинаются с operator, что имеет значение.

Тип, так сказать, является частью имени функции преобразования. На самом деле это не две перегрузки с разным типом возврата, это две разные функции.

StoryTeller - Unslander Monica 20.06.2018 11:42

@StoryTeller, а как насчет того, чтобы добавить это как еще один ответ? Ответы, данные до сих пор, не совсем удовлетворительны ...

Wolf 20.06.2018 12:36

Я считаю, что в самом строгом смысле, даже если это не имеет особого смысла для const, это законно.

Существует разница между объявлением функции и типом функции, и они не имеют одинаковых ограничений.

Функция декларации может не отличаться только типом возвращаемого значения или (начиная с C++ 17) спецификацией исключения. Однако о функции тип ничего такого не говорится (насколько мне известно).

Стандартный [class.conv.fct] описывает функции преобразования как имеющие такую-то форму (перечислены три альтернативы), все из которых не выглядят как обычные объявления функций, в частности, совершенно очевидно, что они не имеют возвращаемого типа.

Это заявляет, тип функции - "функция, не имеющая параметра, возвращающая идентификатор типа преобразования", но нигде не упоминается, что функция преобразования декларации имеет такую ​​вещь, как возвращаемый тип. Напротив, три перечисленные альтернативные формы явно не имеют возвращаемого типа.

Поскольку функции преобразования не имеют возвращаемого типа (... в их объявлении), он не может конфликтовать. Так что, я полагаю, в самом строгом, самом педантичном смысле это даже своего рода «законно», независимо от того, имеет ли это смысл или нет.

Если задуматься, то должно быть тоже как-то законно. Класс вполне может иметь более одной функции преобразования в разные вещи (не только отличаясь const). Такой код действительно существует, и иногда в этом есть большой смысл. Например, у вас может быть класс File, который преобразуется либо в string (имя файла), либо в handle_t (дескриптор операционной системы), если вы хотите использовать какую-то специфичную для ОС или экзотическую функцию, которую ваш класс-оболочка не поддерживает напрямую. (подумайте, writev, tee или epoll?) Это определенно то, что вы ожидаете от работы!
Если, однако, мы будем рассматривать функции преобразования как «просто функции», то они будут отличаться только своим возвращаемым типом, что сделает объявления незаконными. Итак ... это не сработает.

функции преобразования не имеют возвращаемого типа - интересный момент, который учит видеть операторы преобразования не как какие-то функции, а как конструкторы, которые также не имеют возвращаемого типа, но могут использоваться для получения объектов. И приемлемый ответ тоже :)
Wolf 20.06.2018 16:54

Другие вопросы по теме