Можно ли объявлять функции пространства имен в области блока?

Могут ли функции пространства имен быть объявлены в области блока за пределами пространства имен, в котором они были определены?

Этот код не компилируется, когда 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).

Есть ли способ исправить это?

когда объявления находятся за пределами main, это та же проблема, но ошибки намного яснее godbolt.org/z/3o9e6nxqr

463035818_is_not_a_number 31.01.2023 14:29

@ 463035818_is_not_a_number Хм, понятно. Таким образом, кажется, что нет никакого способа обойти это. Отлично.

digito_evo 31.01.2023 14:37

@ Адриан Моул Интересно. Я использую последнюю стабильную версию GCC. На других компиляторах не пробовал.

digito_evo 31.01.2023 14:39
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
61
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я не могу найти окончательной ссылки на это в стандарте, но я не думаю, что было бы много смысла разрешать это намеренно.

Даже если бы это могло появиться в области блока, это было бы бессмысленно. Объявление, использующее спецификатор вложенного имени, не может быть первым объявлением сущности.

[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 31.01.2023 14:49

@digito_evo- Я полагаю, вы имеете в виду обход слежки? Объявление using также достигает этого. И не требуется повторять прототипы.

StoryTeller - Unslander Monica 31.01.2023 14:56

Я имею в виду, что это может быть полезно для функций, которые вызываются только в одной функции foo(), мы можем объявить их локально в foo() и таким образом убедиться, что никто другой в области файла, кроме foo(), не будет иметь доступа к объявлениям этих функций. Это похоже на сокрытие некоторых функций, которые не должны использоваться какой-либо другой частью кода.

digito_evo 31.01.2023 18:49

Другие вопросы по теме