Подтвердить что ты не робот

Ошибка преобразования указателя с помощью оператора Ternary

Я знаю, что у тройного оператора есть некоторые удивительные ограничения, но я был немного озадачен тем, что это не скомпилируется для меня:

void foo(bool b)
{
    int* ptr =  ((b) ? NULL : NULL);
}

Очевидно, что минимум должен был показать проблему. Ошибка:

[BCC32 Error] Unit11.cpp(20): E2034 Cannot convert 'int' to 'int *'

Компилятор - это менее 100% -конформирующий Embarcadero С++ Builder 2010, поэтому ошибка компилятора далека от невозможности...

ПРИМЕЧАНИЕ. Изменены Parens, чтобы избежать путаницы в моих намерениях.

ПРИМЕЧАНИЕ2: Я немного смутился о том, как я пришел к этой конструкции в первую очередь, так что здесь мое оправдание: я получал некоторые ошибки компиляции на строке типа a = b? c : d, где b, c и d - все сложные выражения. Чтобы сузить его, я заменил c и d на NULL, чтобы проверить, был ли b виновником. На данный момент все попало в ад в ручную тележку.

4b9b3361

Ответ 1

NULL - макрос, который расширяется до 0 (или некоторого целочисленного постоянного выражения со значением 0, например, (1 - 1)). Это не иначе "особенное".

Любое целочисленное постоянное выражение со значением нуля может использоваться как константа нулевого указателя, что является причиной того, что int* ptr = 0; разрешено. Однако здесь выражение b ? 0 : 0; это не является интегральным постоянным выражением (b не является константой); его тип int, который неявно конвертируется в int*

Обходным путем было бы явно указать, что вы хотите тип указателя:

int* const null_int_ptr = 0;
int* ptr = b ? null_int_ptr : null_int_ptr;

Пример немного надуман, хотя: обычно, когда вы используете условный оператор, по крайней мере один из аргументов на самом деле является типом указателя (например, b ? ptr : 0); когда один из операндов является типом указателя, 0 неявно преобразуется в тот же самый тип указателя и, следовательно, тип всего условного выражения является типом указателя, а не int.

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

Ответ 2

Ваша проблема в том, что в вашей системе NULL определяется как 0, который считается int в контексте тернарного оператора. Если вы static_cast один из операндов на int*, он должен автоматически продвигать другой.

Но зачем использовать такую ​​конструкцию в первую очередь?

Ответ 3

NULL может быть определен как имеющий тип int или даже long, поэтому тернарный оператор имеет тот же тип. Там нет неявного преобразования в тип указателя, поэтому компилятор генерирует ошибку. Полученная здесь заключается в том, что существует неявное преобразование из константного целочисленного выражения, которое оценивается до нуля (позорная константа нулевого указателя).

Возможное решение здесь - это явное выражение:

int* ptr =  b ? (int*) NULL : NULL;