Член пространства имен может быть определен в пространстве имен, которое охватывает пространство имен объявления:
Члены именованного пространства имен также могут быть определены вне этого пространства имен по явной квалификации (3.4.3.2)
определяемого имени, при условии, что определяемый объект уже был объявлен в пространстве имен
и определение появляется после точки объявления в пространстве имен, которое охватывает декларацию
Пространство имен.
void f();
namespace N { void ::f() {} } // illegal for definition
namespace N { void ::f(); } // what about redeclaration?
Класс может быть определен в пространстве имен, которое содержит пространство имен объявления:
Если class-head-name содержит спецификатор вложенного имени, спецификатор класса должен ссылаться на класс, который был
ранее объявленный непосредственно в классе или пространстве имен, к которому относится спецификатор вложенного имени, или в
элемент встроенного набора пространств имен (7.3.1) этого пространства имен (т. е. не просто наследуется или вводится
декларация об использовании), и спецификатор класса должен появиться в пространстве имен, включающем предыдущее объявление.
В таких случаях спецификатор вложенного имени класса-заголовка определения не должен начинаться с
decltype-спецификатор.
struct A;
namespace N { struct ::A {}; } // illegal for definition
namespace N { struct ::A; } // what about redeclaration?
Также у нас есть одно и то же правило для определения функций-членов и статических данных-членов.
Поэтому мой вопрос заключается в том, является ли переопределение (не определение) законным в пространстве имен, которое не включает в себя первоначальное объявление?
Что касается struct ::A;
, [Dcl.type.elab] / 1 делает ваше заявление некорректным:
Если уточненный тип Спецификатор является единственной составляющей
декларация, декларация не оформлена, если это явный
специализация (14.7.3), явная реализация (14.7.2) или Это
имеет одну из следующих форм:ключ-атрибут-спецификатор-ключ-классавыбирать
идентификатор;
friend
класс-ключ
::
выбирать идентификатор;
friend
класс-ключ::
выбирать простой шаблон-идентификатор;
friend
идентификатор вложенного имени класса
;
friend
спецификатор вложенного имени класса
template
выбирать простой шаблон-идентификатор;
Я не вижу проблемы в случае функции; [Dcl.meaning] / 1 разрешает ли это:
Когда
описатель-идентификатор квалифицировано, объявление должно ссылаться на ранее объявленного члена класса или пространства имен
к которому относится квалификатор (или, в случае пространства имен, элемента встроенного набора пространств имен этого пространства имен (7.3.1)) или к его специализации; […] [ Заметка: Если классификатор является глобальным::
оператор разрешения области действия, описатель-идентификатор относится к объявленному имени
в глобальной области имен. — конечная нота ]
Тем не менее, как GCC, так и Clang настаивают на том, что переопределения как определения должны происходить во вложенном пространстве имен.
Других решений пока нет …