14

This question got me wondering whether it is ever useful/necessary to fully qualify class names (including the global scope operator) in an out-of-class member function definition.

On the one hand, I've never seen this done before (and the syntax to properly do so seems obscure). On the other, C++ name lookup is very non-trivial, so maybe a corner case exists.

Question:

Is there ever a case where introducing an out-of-class member function definition by
ReturnType (::Fully::Qualified::Class::Name::MemberFunctionName)(...) { ... }
would differ from
ReturnType Fully::Qualified::Class::Name::MemberFunctionName(...) { ... } (no global scope :: prefix)?

Note that member function definitions must be put into a namespace enclosing the class, so this is not a valid example.

curiousguy
  • 8,038
  • 2
  • 40
  • 58
Max Langhof
  • 23,383
  • 5
  • 39
  • 72

3 Answers3

12

A using-directive can cause Fully to be ambiguous without qualification.

namespace Foo {
    struct X {
    };
}

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

void X::c() { } // ambiguous
void ::X::c() { } // OK
T.C.
  • 133,968
  • 17
  • 288
  • 421
5

It's necessary if one is a masochist and enjoys writing stuff like this

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

   struct bar {
       void baz();
   };

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

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

One can of course write the second overload as foo::foo::bar::baz in global scope, but the question was whether or not the two declarations can have a different meaning. I wouldn't recommend writing such code.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
2

If a using directive is used then there can be a confusing code.

Consider the following demonstrative program

#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;
}

So for readability this qualified name

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

shows precisely where the function is declared.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335