Почему разные функции преобразования для 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
}

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

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

Ответ 1

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

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

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

запрещены:

error: 'const int mytest :: f() не может быть перегружен

Это просто, что операторы преобразования начинаются с operator что делает разницу.

Ответ 2

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

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

Ответ 3

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

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

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

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

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

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

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

Ответ 4

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

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

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