Un nom de classe complet jusqu'à la portée globale est-il jamais requis pour les définitions de fonctions membres hors ligne?

14

Cette question m'a amené à me demander s'il est jamais utile / nécessaire de qualifier pleinement les noms de classe (y compris l'opérateur de portée globale) dans une définition de fonction membre hors classe.

D'une part, je n'ai jamais vu cela se faire auparavant (et la syntaxe pour le faire correctement semble obscure). De l'autre, la recherche de nom C ++ est très simple, donc peut-être un cas de coin existe.

Question:

Y a-t-il jamais un cas où l'introduction d'une définition de fonction membre hors classe
ReturnType (::Fully::Qualified::Class::Name::MemberFunctionName)(...) { ... }
différerait de
ReturnType Fully::Qualified::Class::Name::MemberFunctionName(...) { ... }(pas de ::préfixe de portée globale )?

Notez que les définitions de fonctions membres doivent être placées dans un espace de noms contenant la classe, ce n'est donc pas un exemple valide.

Max Langhof
la source
Très curieux de ce que le downvoter n'aime pas sur cette question. Bienvenue!
Max Langhof
lorsque la définition est placée dans un espace de noms différent de la déclaration? C'est ce que j'avais en tête pour la question que vous liez
idclev 463035818
oups, je n'ai pas lu les petits caractères;)
idclev 463035818
@ formerlyknownas_463035818 C'est aussi ce que j'avais en tête, puis je l'ai essayé et j'ai réalisé que cela ne fonctionnerait pas, alors j'ai écrit la question (en pensant que les autres se poseraient la question aussi).
Max Langhof

Réponses:

12

Une directive d'utilisation peut Fullyêtre ambiguë sans qualification.

namespace Foo {
    struct X {
    };
}

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

void X::c() { } // ambiguous
void ::X::c() { } // OK
TC
la source
5

C'est nécessaire si on est masochiste et qu'on aime écrire des trucs comme ça

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

   struct bar {
       void baz();
   };

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

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

On peut bien sûr écrire la deuxième surcharge comme foo::foo::bar::bazde portée globale, mais la question était de savoir si les deux déclarations peuvent avoir un sens différent. Je ne recommanderais pas d'écrire un tel code.

Conteur - Unslander Monica
la source
Oui, c'est en effet une réponse valable, et n'a même pas besoin d'un using. C'est bien d'avoir différents cas mis en évidence!
Max Langhof
2

Si une directive using est utilisée, il peut y avoir un code déroutant.

Considérez le programme démonstratif suivant

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

Donc, pour plus de lisibilité, ce nom qualifié

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

montre précisément où la fonction est déclarée.

Vlad de Moscou
la source