Связывание символов в анонимном пространстве имен в пределах обычного пространства имен

В С++ размещение функции или переменной в анонимном пространстве имен делает ее взаимосвязь внутренней, i. е. то же, что и объявление static на уровне файла, но идиоматический С++.

Как насчет анонимного пространства имен в обычном пространстве имен? Гарантирует ли это внутреннюю связь?

// foo.cpp

void func1() {
    // external linkage
}

static void func2() {
    // internal linkage
}

namespace {
    void func3() {
        // internal linkage
    }
}

namespace ns1 {
    void func4() {
        // external linkage
    }

    namespace {
        void func3() {
            // still internal linkage?
        }
    }
}

Ответы

Ответ 1

С++ 11 (черновик N3337) §3.5/4: (акцент мой)

Неименованное пространство имен или пространство имен, объявленное прямо или косвенно в неназванном пространстве имен, имеет внутреннюю привязку. Все остальные пространства имен имеют внешнюю связь. Имя с областью пространства имен, которая не была предоставлена ​​внутренней связью выше, имеет ту же связь, что и охватывающее пространство имен, если это имя

     

- переменная; или

     

- функция; или

     

- именованный класс (раздел 9) или неназванный класс, определенный в объявлении typedef, в котором класс имеет имя typedef для целей привязки (7.1.3); или

     

- именованное перечисление (7.2) или неназванное перечисление, определенное в объявлении typedef, в котором перечисление имеет имя typedef для целей привязки (7.1.3); или

     

- перечислитель, относящийся к перечислению с привязкой; или

     

- шаблон.

Это гарантирует, что любое неназванное пространство имен имеет внутреннюю привязку.

Как насчет анонимного пространства имен в обычном пространстве имен? Гарантирует ли это внутреннюю связь?

Хотя в именованном (нормальном) пространстве имен это неназванное (анонимное) пространство имен и, следовательно, гарантируется внутренняя связь в соответствии со стандартом С++ 11.


размещение функции или переменной в анонимном пространстве имен делает ее взаимосвязь внутренней, т.е. е. то же самое, что объявлять его статическим на уровне файла, но идиоматическим С++.

В С++ 11 использование static в этом контексте было недооценено; хотя неназванное пространство имен является превосходной альтернативой static, есть случаи, когда он не работает, который исправлен на static; inline namespace был введен в С++ 11 для решения этой проблемы.

Ответ 2

Не обязательно, чтобы объекты в анонимном пространстве имен имели внутреннюю связь; они могут иметь внешнюю связь.

Так как неназванное пространство имен имеет имя, уникальное для единицы перевода, в котором оно было скомпилировано, вы просто не можете ссылаться на сущности, объявленные в нем из-за пределов этой единицы перевода, независимо от их привязки.

В стандарте С++ говорится (С++ 03 7.3.1.1/note 82):

Хотя объекты в неназванном пространстве имен могут иметь внешнюю связь, они эффективно квалифицируются по имени, уникальному для их единицы перевода, и поэтому никогда не могут быть замечены из любой другой единицы перевода.

Ответ 3

$3.5/3 - "Имя, имеющее пространство имен сфера (3.3.6) имеет внутреннюю связь, если это имя

- переменная, функции или функции, которая явно объявлено статическим; или,

- a переменная, которая явно объявлена const и не объявлено явно извне или ранее объявлен внешняя связь; или

- член данных анонимного союза.

Итак, я сомневаюсь, что какое-либо из имен func3 и func4 в вашей программе имеет внутреннюю связь вообще. Они имеют внешнюю связь. Тем не менее, они просто не могут быть переданы из других единиц перевода в соответствии с цитатой Джеймса.