Разрешено ли стандартом следующее?
#include <iostream>
extern int a;
auto a = 3;
int main(int, char**)
{
std::cout << a << std::endl;
return 0;
}
clang принимает код. g++ жалуется на противоречивое объявление.
Разрешено ли стандартом следующее?
#include <iostream>
extern int a;
auto a = 3;
int main(int, char**)
{
std::cout << a << std::endl;
return 0;
}
clang принимает код. g++ жалуется на противоречивое объявление.
Мне не очень понятно из стандарта, но там же написано
раздел 7.1.6.4 спецификатор auto
Программа, использующая auto в контексте, явно не разрешенном в этом разделе, имеет неправильный формат.
Лучше прочитайте упомянутый раздел стандарта для всех разрешенных контекстов.
Учитывая это, я считаю, что g++ правильный, а clang неправильный. Но я могу ошибаться, в стандарте может быть какой-то отдельный раздел, который может подразумевать этот контекст, но я не смог его найти.
auto a = 3;
здесь явно разрешен контекст. Такое использование разрешено при объявлении переменных в блоке (6.3), в области пространства имен (3.3.6), [...]
- person M.M; 24.05.2016
Изменить ответ: как указано в комментариях. Проблема в этом случае в том, что написание
external int a;
auto a = 3;
то же, что писать
external int a;
int a = 3;
это означает, что у вас есть новое определение a, и это вызывает ошибку.
Первый ответ: насколько я понимаю, это нарушает части правила единого определения. В частности, я имею в виду следующее правило (со ссылкой на MISRA C++ 2008), которое гласит, что идентификатор с внешней связью всегда должен иметь только одно определение. В вашем примере у вас есть определение в текущем файле (auto a = 3;
), а с внешним вы также ссылаетесь на определение в другом файле.
auto a
не противоречит исходному объявлению. Extern не нужно ссылаться на определение в другом файле. Он просто ссылается на определение в каком-то файле. Можно определить переменную в том же файле, где она была объявлена как extern.
- person eerorika; 24.05.2016
a
. Конечно, если вы добавите больше определений, связав эту ЕП с другими ЕП, вы можете нарушить ODR, но я не думаю, что вопрос об этом, поскольку это не имеет ничего общего с auto
.
- person Steve Jessop; 24.05.2016
extern int a;
— это объявление, int a = 3;
— это определение
- person M.M; 24.05.2016
extern
, не могли включать тот же заголовочный файл, который включают все остальные, содержащий объявление extern
. К счастью, им разрешено, и это все, что вы здесь видите. Это ЕП, которая содержит (одно) определение a
, а также ее объявление extern
.
- person Steve Jessop; 24.05.2016
extern int a; int a = 3;
будет правильным кодом. Передекларация в порядке. Повторное объявление с неправильным типом недопустимо. Здесь auto
будет выводиться как int
, что является правильным типом, но g++ и msvc жалуются на конфликтующее объявление. Итак, вопрос в том, можно ли использовать auto
в повторных декларациях.
- person eerorika; 24.05.2016
error C2371: 'a' : redefinition; different basic types
. - person nabroyan   schedule 24.05.2016extern int a; decltype(a) a;
;) - person Ajay   schedule 24.05.2016auto
указывает тип, отличный отint
дляa
, но даже если вы это утверждаете, я вполне уверен, что цель состоит в том, чтобы этот код был законным. - person M.M   schedule 24.05.2016auto
не является типом, поэтому мы не можем сказать, что они не идентичны, потому что типыint
иauto
являются разными типами. Текст не имеет смысла, если вы не считаете, что тип означает тип, выведенныйauto
- person M.M   schedule 24.05.2016auto
. На самом деле, возможно, я должен считать, чтоauto
уже является частью типа, указанного во втором объявлении, не говоря уже о каких-либо корректировках :-) - person Steve Jessop   schedule 24.05.2016