Связывание различных константных / статических переменных

У меня есть несколько вопросов о связи из следующих переменных. На примерах 7.1.1 / 7 C ++ 03 и экспериментов с компиляторами (Comeau, Clang и GCC) я пришел к следующим видам связей:

  1. Сначала static , затем extern

     static int a; // (а)
    extern int a; // (b) действительный, 'a' все еще внутренний
    

    Для меня ясно, в соответствии с разделом 3.5: (а) подразумевает внутреннюю связь. И (б) также подразумевает внутреннюю связь, потому что имя «а» объявлено статическим (в соответствии с (а)).

  2. Сначала extern , затем static

     extern int b; // (с)
    static int b; // (d) неверно!
    

    Во-первых, (с) подразумевает внешнюю связь. Но (d) подразумевает внутреннюю связь, потому что имя "b" объявлено статическим (d). Это неверно в соответствии с 7.1.1 / 7, поскольку подразумеваемая связь не является согласованной.

  3. Сначала const , затем extern

     const double pi1 = 3,14; // (e)
    extern const double pi1; // (f) действителен, а 'pi1' является внутренним
    

    Во-первых, (e) подразумевает внутреннюю связь, потому что она является const, и не объявляется явной внешней или ранее подразумеваемой внешней связью. И (f) должно подразумевать внешнее связывание и быть ошибкой, потому что оно явно объявляет имя extern, но компиляторы сохраняют его внутренним! Почему так? Это мой вопрос.

  4. Сначала 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) , то две интерпретации приходят к разным выводам, как показано ниже

  1. Первая интерпретация отмечает, что pi1 объявлен const , но также объявлен extern . Таким образом, переменная имеет внешнюю связь.

  2. Второе толкование интерпретирует оба случая «объявленного» как ссылку на одно и то же объявление. Таким образом, это означает, что он объявлен const , но не extern const . Отметим, что (e) объявлен const , а не extern const , поэтому мы даем pi1 внутреннюю связь. 12229 Теперь, какая интерпретация верна? Я не могу определить из этой формулировки, но компиляторы, похоже, интерпретируют это вторым способом. В частности, если мы возьмем первую интерпретацию, то последняя цитируемая часть 3.5 / 3 будет излишней, потому что не будет действительного сценария, в котором имя будет объявлено const и ранее объявлено с внешней связью, но без явного extern .

6
задан Community 23 May 2017 в 11:46
поделиться