Связь символов в анонимном пространстве имен в обычном пространстве имен - PullRequest
14 голосов
/ 15 ноября 2010

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

Как насчет анонимногопространство имен в нормальном пространстве имен?Это все еще гарантирует внутреннюю связь?

// 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?
        }
    }
}

Ответы [ 3 ]

15 голосов
/ 15 ноября 2010

Это не обязательно тот случай, когда сущности в анонимном пространстве имен имеют внутреннюю связь; на самом деле они могут иметь внешнюю связь.

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

Стандарт C ++ гласит (C ++ 03 7.3.1.1/note 82):

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

12 голосов
/ 21 октября 2013

C ++ 11 (черновик N3337) §3.5 / 4: (выделено мной)

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

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

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

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

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

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

- шаблон.

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

А как насчет анонимного пространства имен в обычном пространстве имен? Это все еще гарантирует внутреннюю связь?

Хотя в пределах именованного (нормального) пространства имен оно является безымянным (анонимным) пространством имен и, таким образом, гарантированно будет иметь внутреннюю связь в соответствии со стандартом C ++ 11.


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

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

5 голосов
/ 15 ноября 2010

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

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

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

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

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

...