У меня есть несколько вопросов о связи из следующих переменных.На примерах 7.1.1 / 7 C ++ 03 и экспериментов с компиляторами (Comeau, Clang и GCC) я пришел к следующим видам связей:
Первый static
,тогда extern
static int a; // (a)
extern int a; // (b) valid, 'a' still internal
Для меня ясно, что в соответствии с разделом 3.5: (а) подразумевает внутреннюю связь.И (б) также подразумевает внутреннюю связь, потому что имя «а» объявлено статическим (в соответствии с (а)).
Сначала extern
, затем static
extern int b; // (c)
static int b; // (d) invalid!
Сначала (c) подразумевает внешнюю связь.Но (d) подразумевает внутреннюю связь, потому что имя "b" объявлено статическим (d).Это неверно в соответствии с 7.1.1 / 7, поскольку подразумеваемая связь не является согласованной.
Сначала const
, затем extern
const double pi1 = 3.14; // (e)
extern const double pi1; // (f) valid and 'pi1' is internal
Во-первых, (e) подразумевает внутреннюю связь, так как она является const, и не объявлена явной как extern, так иранее подразумеваемая внешняя связь.И (f) должно подразумевать внешнее связывание и быть ошибкой, потому что оно явно объявляет имя extern, но компиляторы сохраняют его внутренним! Почему так? Это мой вопрос.
Сначала extern
, затем const
extern const double pi2; // (g)
const double pi2 = 3.14; // (h) valid and 'pi2' is external
Сейчас(g) подразумевает внешнюю связь, потому что мы явно объявили extern.И (h) также подразумевает внешнюю связь, потому что (g) явно объявлен extern.
Я экспериментально обнаружил связь для 3 и 4 со следующим шаблоном (второй аргумент необходим для внешней связи)
template<typename T, T&> struct ensure { };
ensure<const double, pi1> e1; // failed
ensure<const double, pi2> e2; // succeeded
Резюме: Обсуждение с Чарльзом Бэйли оказалось весьма плодотворным и показало, что есть два возможных толкования 3.5/3
, где важный пункт маркированного текста гласит:
Имя, имеющее область пространства имен (3.3.5), имеет внутреннюю связь, если оно является именем
- объекта или ссылки, которая явно объявлена как const и ни явно не объявлена как extern, ни ранее объявленаиметь внешнюю связь;
Если мы посмотрим на точку (f)
, то две интерпретации приходят к разным выводам, как показано ниже
Первая интерпретация отмечает, чтоpi1
объявлен const
, но также объявлен extern
.Таким образом, переменная имеет внешнюю связь.
Второе толкование интерпретирует оба случая «объявленного» как ссылку на одно и то же объявление.Таким образом, это означает, что оно объявлено const
, но не extern const
.Мы отмечаем, что (e)
объявлен const
, а не extern const
, поэтому мы даем pi1
внутреннюю связь.
Какое толкование верно?Я не могу определить из этой формулировки, но компиляторы, похоже, интерпретируют это по-другому.В частности, если мы возьмем первую интерпретацию, тогда последняя цитируемая часть 3.5/3
будет излишней, потому что не будет никакого действительного сценария, в котором имя будет объявлено const
и ранее объявлено с внешней связью, но без явногоextern
.