Существуют ли правила неявного преобразования типов для аргументов тернарного оператора?
Тернарный оператор всегда должен возвращать один и тот же тип. Этот тип определяется исключительно вторым и третьим аргументом (1st ? 2nd : 3rd
), поэтому оба аргумента преобразуются в этот тип. Как определяется этот тип?
Чтобы быть более конкретным, я протестировал пример:
class pointclass
{
pointclass();
pointclass( int i ); // (pointclass)(int)
operator bool() const; // (bool)(pointclass)
};
У меня есть класс (pointclass
), что позволяет неявное преобразование из int
в pointclass
и неявное преобразование из pointclass
в bool
,
int i;
pointclass p;
bool b;
b ? p : i; // (bool) ? (int)(bool)(pointclass) : (int)
b ? i : p; // (bool) ? (int) : (int)(bool)(pointclass)
Используя троичный оператор, я сравниваю pointclass
а также int
, Компилятор использует неявное преобразование из pointclass
в bool
а затем стандартное преобразование из bool
в int
, Это сделано, независимо от того, обмениваюсь ли я вторым и третьим аргументами. Почему это не конвертировать int
в pointclass
?
Использование оператора сравнения намного проще:
p == i; // (pointclass) == (pointclass)(int)
i == p; // (int) == (int)(bool)(pointclass)
Тип аргументов просто определяется первым аргументом.
Но я не понимаю правила преобразования типов троичного оператора. Для меня это похоже на использование большинства конверсий.
квотирование MSDN:
Условные выражения имеют ассоциативность справа налево. Первый
операнд должен иметь целочисленный или указательный тип. Применяются следующие правила
ко второму и третьему операндам:Если оба операнда имеют один и тот же тип, результат будет того же типа.
Если оба операнда имеют арифметический или перечислимый типы, обычные арифметические преобразования (описанные в арифметических преобразованиях)
выполняется для преобразования их в общий тип.Если оба операнда имеют тип указателя или один является типом указателя, а другой является константным выражением, значение которого равно 0, указатель
преобразования выполняются для преобразования их в общий тип.Если оба операнда относятся к ссылочным типам, выполняется преобразование ссылок для преобразования их в общий тип.
Если оба операнда имеют тип void, общий тип имеет тип void.
Если оба операнда имеют один и тот же определенный пользователем тип, общим типом является этот тип.
Если операнды имеют разные типы, и, по крайней мере, один из операндов имеет определенный пользователем тип, то языковые правила используются для
определить общий тип. (См. Предупреждение ниже.)
В основном происходит то, что компилятор C ++ ищет общий тип для второго и третьего операнда. Если он может найти его, это тип результата. Если это не может найти это, это приводит к ошибке времени компиляции.
Если вы хотите увидеть стандартную позицию, вы можете увидеть правила в рабочем проекте для новейшего стандарта, 5,16 (стр. 129).
Начиная с преобразования int в pointclass — общее правило таково, что вы всегда идти вниз по иерархии, а не вверх — представьте себе более продвинутую иерархию классов; где-то там могут быть десятки способов конвертировать оба типа в какой-то другой класс, но действительно ли это то, что вы хотите? Более того, определить, какой класс использовать, невозможно. Поэтому мы удручены.