У меня есть несколько вопросов о связи из следующих переменных. На примерах 7.1.1 / 7 C ++ 03 и экспериментов с компиляторами (Comeau, Clang и GCC) я пришел к следующим видам связей:
Сначала static
, затем extern
static int a; // (а)
extern int a; // (b) действительный, 'a' все еще внутренний
Для меня ясно, в соответствии с разделом 3.5: (а) подразумевает внутреннюю связь. И (б) также подразумевает внутреннюю связь, потому что имя «а» объявлено статическим (в соответствии с (а)).
Сначала extern
, затем static
extern int b; // (с)
static int b; // (d) неверно!
Во-первых, (с) подразумевает внешнюю связь. Но (d) подразумевает внутреннюю связь, потому что имя "b" объявлено статическим (d). Это неверно в соответствии с 7.1.1 / 7, поскольку подразумеваемая связь не является согласованной.
Сначала const
, затем extern
const double pi1 = 3,14; // (e)
extern const double pi1; // (f) действителен, а 'pi1' является внутренним
Во-первых, (e) подразумевает внутреннюю связь, потому что она является const, и не объявляется явной внешней или ранее подразумеваемой внешней связью. И (f) должно подразумевать внешнее связывание и быть ошибкой, потому что оно явно объявляет имя extern, но компиляторы сохраняют его внутренним! Почему так? Это мой вопрос.
Сначала extern
, затем const
extern const double pi2; // (г)
const double pi2 = 3,14; // (h) действителен, а 'pi2' является внешним
Теперь, (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 и ни явно не объявлены как внешние, так и ранее объявленный иметь внешнюю связь;
Если мы посмотрим на пункт (f)
, то две интерпретации приходят к разным выводам, как показано ниже
Первая интерпретация отмечает, что pi1
объявлен const
, но также объявлен extern
. Таким образом, переменная имеет внешнюю связь.
Второе толкование интерпретирует оба случая «объявленного» как ссылку на одно и то же объявление. Таким образом, это означает, что он объявлен const
, но не extern const
. Отметим, что (e)
объявлен const
, а не extern const
, поэтому мы даем pi1
внутреннюю связь. 12229 Теперь, какая интерпретация верна? Я не могу определить из этой формулировки, но компиляторы, похоже, интерпретируют это вторым способом. В частности, если мы возьмем первую интерпретацию, то последняя цитируемая часть 3.5 / 3
будет излишней, потому что не будет действительного сценария, в котором имя будет объявлено const
и ранее объявлено с внешней связью, но без явного extern
.