Неявное преобразование в C ++

В C ++ я пытаюсь использовать неявное преобразование с условным оператором. Рассмотрим этот пример:

class MyFloat
{ 
    public:                                                                    
        MyFloat(float val){m_val = val;}
        operator float(){return m_val;}
    protected:
        float m_val;
};

int main(int argc, char **argv)
{
    MyFloat a = 0.5f;
    MyFloat b = 1.0f;                            
    float x = true ? a-0.5f : b;
    return 0;
}

Это вызывает ошибку компилятора:

error: operands to ?: have different types ‘MyFloat’ and ‘float’

Я ожидаю, что условный оператор неявно преобразует b в тип a-0.5, float. Но этого не происходит. Как добиться этого неявного приведения?

В идеале я хочу избежать статического приведения или метода доступа, такого как float MyFloat::getValue().


person ethan    schedule 06.02.2013    source источник
comment
Вы начали хорошо с неявного преобразования, а затем проиграли его с неявным приведением. Приведение - это то, что вы пишете в исходном коде, чтобы сообщить компилятору о необходимости преобразования. Нет такой вещи, как неявное приведение.   -  person Pete Becker    schedule 07.02.2013
comment
Я просто попытался скомпилировать и запустить ваш код в MS Visual Studio 2012 Professional. 0 ошибок, 0 предупреждений, работает нормально.   -  person LihO    schedule 07.02.2013
comment
@LihO, он не работает в GCC: ideone.com/9WPniF   -  person Mark Ransom    schedule 07.02.2013
comment
Если вы должны определить неявное преобразование, все же может быть полезно определить функцию-член, которая делает точно то же самое, для таких случаев, как этот, проходя через ... и т. Д. Добавление float MyFloat::getValue() const не сделает ваш интерфейс хуже, чем он уже есть. : это добавляет возможность кому-то получить поплавок, точно говоря, что они делают, когда вы уже дали возможность получить поплавок, даже не имея в виду.   -  person aschepler    schedule 07.02.2013


Ответы (3)


Проблема в том, что есть два преобразования. Компилятор может преобразовать a-0.5 в MyFloat или b в float. Пока у вас есть оба преобразования, и ни один из них не отмечен explicit, вы будете постоянно сталкиваться с подобной неоднозначностью.

person Pete Becker    schedule 06.02.2013
comment
Спасибо за ответ и исправление по поводу преобразования и преобразования. - person ethan; 07.02.2013

Только некоторые преобразования сделаны для вас. Из http://msdn.microsoft.com/en-us/library/e4213hs1(v=vs.71).aspx

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

  • Если оба выражения имеют один и тот же тип, результат будет того же типа.
  • Если оба выражения относятся к арифметическому или перечислимому типу, для преобразования их в общий тип выполняются обычные арифметические преобразования (описанные в разделе «Арифметические преобразования»).
  • Если оба выражения относятся к типам указателей или если одно является типом указателя, а другое является константным выражением, значение которого равно 0, выполняется преобразование указателя для преобразования их в общий тип.
  • Если оба выражения относятся к ссылочным типам, выполняется преобразование ссылок для преобразования их в общий тип.
  • Если оба выражения относятся к типу void, общим типом является тип void.
  • Если оба выражения относятся к заданному типу класса, общим типом является этот тип класса.
person krsteeve    schedule 06.02.2013
comment
Это объясняет, почему @LihO скомпилировал его с помощью Visual Studio. Но эти правила не соответствуют определению языка. - person Pete Becker; 07.02.2013
comment
Я тоже это видел, но это несовместимо с другой ссылкой: en.cppreference.com/ w / cpp / language / - person Mark Ransom; 07.02.2013

Если я правильно помню, тернарный оператор не выполняет никакого неявного преобразования. Вам нужно будет либо написать

static_cast<MyFloat>(a-0.5) 

or

static_cast<float>(b). 

Я покопаюсь в документации по стандартам C ++, когда вернусь домой, чтобы получить более подробную информацию.

person bstamour    schedule 06.02.2013
comment
Компилятор преобразует два аргумента в их общий тип. - person Pete Becker; 07.02.2013
comment
Хорошо, тогда не стесняйтесь игнорировать этот ответ. Я также голосую за ваш ответ, поскольку, вероятно, это причина того, что его код не компилируется. - person bstamour; 07.02.2013