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

Почему "int x = +" foo "; ошибка типа, но не синтаксическая ошибка?

Все компиляторы Я попытался правильно отклонить код

int main() {
  int x = "foo";
}

с ошибкой типа: const char[4] не может быть преобразован в int. Почему одни и те же компиляторы (включая Ideone.com) дают ту же ошибку для

int main() {
  int x = + "foo";
}

вместо (как я думал) синтаксической ошибки из-за знака +? Моя первая идея заключалась в том, что const char[4] распадается на указатель, который, в свою очередь, рассматривается как целое значение, поэтому + обозначает "положительный". Кажется немного надуманным, хотя, и я бы ожидал увидеть const char* в сообщении об ошибке.

4b9b3361

Ответ 1

Синтаксис не включает типы в смысле системы типов (ints и символы и указатели), только типы в синтаксическом смысле ключевых слов, операторов, выражений. В синтаксисе С++ + является унарным префиксным оператором, который может предшествовать выражению. "foo" - выражение. Следовательно, +"foo" является допустимым выражением в отношении парсера.

Ваша идея о том, что константа строки распадается на указатель, а + - нет-op на указателях, верна, и следующая программа даже компилируется и запускается:

#include <iostream>

int main()
{
    const char *message = +"Hello!\n";
    std::cout << message;
}

... но это не имеет значения. То, что вы видите, это ошибка типа, а не синтаксическая ошибка.

EDIT Возможно, еще более убедительным является тот факт, что вы можете перегрузить унарный +:

#include <iostream>

struct SomeType {
    const char *operator+() const
    {
        return "Hello, world!\n";
    }
};

int main()
{
    SomeType x;
    std::cout << +x;
}

Ответ 2

Унарный + применяется к указателям, и он просто возвращает значение типа и не выполняет целые акции по указателям, поэтому результат является указателем, а не интегральным типом, из стандартного раздела проекта С++ 5.3.1 Унарные операторы:

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

строковый литерал представляет собой массив из const char, from 2.14.5 Строковые литералы:

[...] Узкий строковый литерал имеет тип "массив из n const char", [...]

который будет распадаться на указатель в этом контексте.

Ответ 3

Унарный оператор + может применяться к типам указателей:

С++ 11 5.3.1 [expr.unary.op]/7: операнд унарного + оператора должен иметь арифметическое, неперечисленное перечисление или тип указателя, и результатом будет значение аргумента.

Итак, литеральный массив преобразуется в const char *, а оператор применяется к этому указателю, прежде чем не назначить указатель на int так же, как в первом примере.

Ответ 4

Почему "int x = +" foo "; ошибка типа, но не синтаксическая ошибка?

Потому что синтаксическая ошибка отсутствует. Существует семантическая ошибка.

После синтаксического анализа оператора компилятор определяет, возможна ли такая инициализация. Фактически синтаксически утверждение выглядит как

int x = + ( expression );

Синтаксически это утверждение верно. Кроме того, унарный плюс может применяться к указателям.