Требуется ли когда-либо полностью определенное имя класса до глобальной области видимости для внешних определений функций-членов?

14

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

С одной стороны, я никогда не видел, чтобы это было сделано раньше (и синтаксис для правильной работы кажется неясным). С другой стороны, поиск имени в C ++ очень нетривиален, поэтому, возможно, существует угловой случай.

Вопрос:

Был ли когда-нибудь случай, когда введение определения функции-члена вне класса
ReturnType (::Fully::Qualified::Class::Name::MemberFunctionName)(...) { ... }
отличалось бы от
ReturnType Fully::Qualified::Class::Name::MemberFunctionName(...) { ... }(без ::префикса глобальной области видимости )?

Обратите внимание, что определения функций-членов должны быть помещены в пространство имен, включающее класс, так что это недопустимый пример.

Макс Лангоф
источник
Очень любопытно, что даунвотеру не нравится в этом вопросе. Обратная связь приветствуется!
Макс
когда определение помещается в другое пространство имен, чем объявление? Вот что я имел в виду для ссылки, которую вы связываете
idclev 463035818
упс, не прочитал мелкий шрифт;)
idclev 463035818
@ beforelyknownas_463035818 Это также то, что я имел в виду, затем я попробовал это и понял, что это не будет работать, поэтому я написал вопрос (полагая, что другие тоже удивятся).
Макс

Ответы:

12

С помощью директивы может привести Fullyк неоднозначным без квалификации.

namespace Foo {
    struct X {
    };
}

using namespace Foo;
struct X {
    void c();
};

void X::c() { } // ambiguous
void ::X::c() { } // OK
TC
источник
5

Это необходимо, если кто-то мазохист и любит писать такие вещи, как это

namespace foo {
    namespace foo {
        struct bar {
            void baz();
        };
    }

   struct bar {
       void baz();
   };

   void foo::bar::baz() {
   }

   void (::foo::bar::baz)() {
   }
} 

Конечно, можно написать вторую перегрузку, как foo::foo::bar::bazв глобальной области видимости, но вопрос заключался в том, могут ли два объявления иметь разное значение. Я бы не рекомендовал писать такой код.

Рассказчик - Unslander Monica
источник
Да, это действительно правильный ответ, и он даже не нужен using. Приятно выделять разные случаи!
Макс
2

Если используется директива using, то здесь может быть запутанный код.

Рассмотрим следующую демонстрационную программу

#include <iostream>
#include <string>

namespace N1
{
    struct A
    {
        void f() const;
    };      
}

using namespace N1;

void A::f() const { std::cout << "N1::f()\n"; }

struct A
{
    void f() const;
};

void ::A::f() const { std::cout << "::f()\n"; }

int main() 
{
    N1::A().f();
    ::A().f();

    return 0;
}

Так что для удобства чтения это квалифицированное имя

void ::A::f() const { std::cout << "::f()\n"; }

показывает точно, где функция объявлена.

Влад из Москвы
источник