Могут ли функции пространства имен быть объявлены в области блока за пределами пространства имен, в котором они были определены?
Этот код не компилируется, когда DECLARED_IN_NS
определяется как 1
:
#define DECLARED_IN_NS 1 // can be either 0 or 1
#if DECLARED_IN_NS == 1
namespace ns
{
#endif
void
func1()
{
}
void
func2()
{
}
#if DECLARED_IN_NS == 1
} // namepace ns
#endif
int main( )
{
#if DECLARED_IN_NS == 1
void ns::func1(); // compile error
void ns::func2(); // compile error
ns::func1();
ns::func2();
#elif DECLARED_IN_NS == 0
void func1();
void func2();
func1();
func2();
#endif
}
Он показывает некоторые ошибки:
error: qualified-id in declaration before '(' token
28 | void ns::func1();
| ^
Код компилируется, когда func1
и func2
определены в глобальном пространстве имен. Однако он не компилируется, если они определены внутри пространства имен (например, ns
).
Есть ли способ исправить это?
@ 463035818_is_not_a_number Хм, понятно. Таким образом, кажется, что нет никакого способа обойти это. Отлично.
@ Адриан Моул Интересно. Я использую последнюю стабильную версию GCC. На других компиляторах не пробовал.
Я не могу найти окончательной ссылки на это в стандарте, но я не думаю, что было бы много смысла разрешать это намеренно.
Даже если бы это могло появиться в области блока, это было бы бессмысленно. Объявление, использующее спецификатор вложенного имени, не может быть первым объявлением сущности.
[dcl.meaning.general]
1 Когда declarator-id является квалифицированным, объявление должно ссылаться на ранее объявленный член класса или пространства имен, на которое ссылается квалификатор (или, в случае пространства имен, элемент встроенного набора пространств имен из это пространство имен ([namespace.def])) ...
Это делает этот код действительным
namespace ns
{
void func();
} // namepace ns
void ns::func(); // repeated declaration - optional
void ns::func() { // definition
}
Теперь, возвращаясь к случаю с блочной областью видимости, вам в любом случае потребуется предваряющее ее объявление с областью видимости пространства имен, так что все это упражнение спорно.
Кроме того, поведение объявления функций в блочной области имеет аспекты, которые удачно названы сообществом C++, но остаются из-за совместимости с C. Было бы определенно нецелесообразно намеренно разрешать его для вложенных имен.
Это может помочь сделать код менее подверженным ошибкам и более понятным в нескольких конкретных сценариях. Но да, в целом это не так уж и полезно. Я вернусь к объявлению в области пространства имен.
@digito_evo- Я полагаю, вы имеете в виду обход слежки? Объявление using также достигает этого. И не требуется повторять прототипы.
Я имею в виду, что это может быть полезно для функций, которые вызываются только в одной функции foo()
, мы можем объявить их локально в foo()
и таким образом убедиться, что никто другой в области файла, кроме foo()
, не будет иметь доступа к объявлениям этих функций. Это похоже на сокрытие некоторых функций, которые не должны использоваться какой-либо другой частью кода.
когда объявления находятся за пределами
main
, это та же проблема, но ошибки намного яснее godbolt.org/z/3o9e6nxqr