Точка объявления для ключевого слова auto
У меня был Q & A до: Точка декларации в С++. Правило-точка-декларация хорошо применима во многих ситуациях. Теперь я смутил использование auto
в сочетании с этим правилом.
Рассмотрим эти два кода:
я. Объявление x
само по себе (мы не ожидаем его работы):
{
auto x = x;
}
II. Объявление внутреннего x
внешним x
(оно делает ошибку в gcc 4.8.x):
{
int x = 101; // the outer x
{
auto x = x; // the inner x
}
}
Согласно правилу пункта декларации, он должен работать, но это не так. Кажется, в стандарте есть еще одно правило, которое я пропустил. Вопрос в том, что Где точка объявления при использовании auto
?
Есть две возможности:
я. Если точка объявления после =
, в конце инструкции:
auto object = expression;
^
Is it here? If it is, why gcc complains?
Таким образом, второе объявление является действительным и должно работать, потому что нет x
, а внешнего (что объявлено ранее). Поэтому auto x=x
допустим, а внутренний x
должен быть назначен 101
.
II. Если точка объявления находится перед =
:
auto object = expression;
^
Ну, это не имеет никакого смысла, потому что auto
должен ждать, пока не увидит следующее выражение. Например, auto x;
недействителен.
Обновить. Мне нужен ответ, который объясняет это точкой правила объявления.
Ответы
Ответ 1
auto x = x; // inner x
плохо сформировался.
Чтобы привести цитату из стандарта С++ 11 (выделение мое):
7.1.6.4 авто-спецификатор
...
3 В противном случае тип переменной выводится из ее инициализатора. Имя объявляемой переменной не будет отображаться в выражении инициализатора....
Итак, поскольку x
после =
разрешается x
в auto x
(как объяснялось в связанном вами вопросе), это выше фрагмент кода плохо сформирован.
Ответ 2
Как и в любом другом определении, x
в правой части инициализатора для auto x = x
разрешается локальному auto x
. С++ всегда делал это (т.е. int x = x
компилирует, но дает вам поведение undefined).
Причина auto x = x
не удается скомпилировать, потому что пока x
находится в области видимости, он еще не имеет известного типа и поэтому использует его как инициализатор, потому что тип не может быть выведен из выражения.
Как и любой другой вид объявления, x
находится в области видимости после своего объявления, которое auto x
.
int x = 10;
int y = 20;
{
int x = x; // This is NOT the outer x. This is undefined behaviour (reading an
// uninitialised variable).
auto y = y; // This is NOT the outer y. This is a compile error because the type of
// y is not known.
}
Ответ 3
Просто добавьте пример с более явной диагностикой:
auto ll = [&] { ll(); };
Результаты в (gcc):
error: variable ‘auto ll’ with ‘auto’ type used in its own initializer
или (clang):
error: variable 'll' declared with 'auto' type cannot appear in its own initializer
auto ll = [&] { ll(); };
^
Вы можете видеть, что для этого существует явное правило. Я не смотрел спецификации.
Ответ 4
Компилятор читает целое утверждение (от начала строки до следующей полутопликации), а затем оценивает различные части оператора с использованием приоритетов операций, а затем, когда приходит время, когда значение auto x
должен быть присвоен тип, который появился после того, как принят знак =
.
Например:
template <typename T>
T sum(T a, T b)
{
return a+b;
}
int main()
{
auto x = sum<double>(1,5); // x here is a double, because the return value is double
auto y = sum<int>(1,7); //y is an int, because the return value is int
}
И о вашем auto x = x
, вы переопределяете одно и то же имя переменной. Это недействительно! auto y = x
будет работать.