Связывание символов в анонимном пространстве имен в пределах обычного пространства имен
В С++ размещение функции или переменной в анонимном пространстве имен делает ее взаимосвязь внутренней, 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 в вашей программе имеет внутреннюю связь вообще. Они имеют внешнюю связь. Тем не менее, они просто не могут быть переданы из других единиц перевода в соответствии с цитатой Джеймса.