2017-08-01 10 views
3

Considérant cet exemple décrit dans http://en.cppreference.com/w/cpp/language/adl:C++ recherche ordinaire vs recherche dépendante de l'argument

namespace A { 
     struct X; 
     struct Y; 
     void f(int); 
     void g(X); 
} 

namespace B { 
    void f(int i) { 
     f(i); // calls B::f (endless recursion) 
    } 
    void g(A::X x) { 
     g(x); // Error: ambiguous between B::g (ordinary lookup) 
       //  and A::g (argument-dependent lookup) 
    } 
    void h(A::Y y) { 
     h(y); // calls B::h (endless recursion): ADL examines the A namespace 
       // but finds no A::h, so only B::h from ordinary lookup is used 
    } 
} 

Je me demande pourquoi l'ambiguïté apparaît puisque les règles ADL ne sont pas prises en compte si

« la recherche L'ensemble produit par la recherche habituelle non qualifiée contient l'un des éléments suivants ".

ici B :: g peut être trouvée en recherche non qualifié comme expliqué dans http://en.cppreference.com/w/cpp/language/unqualified_lookup grâce à la règle

Pour un nom utilisé dans la définition d'une fonction, que ce soit dans son corps ou dans le cadre de argument par défaut, où la fonction est un membre de l'espace de noms déclaré par l'utilisateur ou global, le bloc dans lequel le nom est utilisé est recherché avant l'utilisation du nom, puis le bloc englobant est recherché avant le début de ce bloc, etc. atteindre le bloc qui est le corps de la fonction. Ensuite, l'espace de noms dans lequel la fonction est déclarée est recherchée jusqu'à ce que la définition (pas nécessairement la déclaration) de la fonction qui utilise le nom, puis les encaissantes espaces de noms, etc.

Alors ma question est pourquoi sont les règles ADL considérés comme dans ce cas?

+0

Pourriez-vous expliquer pourquoi vous pensez qu'il ne devrait pas être pris en compte? – cpplearner

+0

Tout d'abord, la recherche dépendant de l'argument n'est pas prise en compte si l'ensemble de recherche produit par la recherche non qualifiée habituelle contient: – FlashMcQueen

+0

1) une déclaration d'un membre de classe 2) une déclaration d'une fonction à la portée du bloc (ce n'est pas un using-declaration) 3) toute déclaration qui n'est pas une fonction ou un modèle de fonction (par exemple un objet fonction ou une autre variable dont le nom est en conflit avec le nom de la fonction recherchée) – FlashMcQueen

Répondre

1

pourquoi les règles ADL (argument dependent-lookup) sont-elles considérées dans ce cas?

Parce qu'il peut y avoir de meilleures correspondances dans les espaces de noms associés. Par exemple:

void f(void*); 

namespace A { 
struct X; 
void f(X*); 
} 

int main() { 
    A::X* x = 0; 
    f(x); // A::f is the best match. 
} 

Ce mécanisme est souvent utilisé pour swap function:

std::swap peuvent être spécialisés dans l'espace de noms std pour les types définis par l'utilisateur, mais ces spécialisations ne sont pas trouvées par ADL (l'espace de noms std est pas l'espace de noms associé pour le type défini par l'utilisateur). La manière attendue de rendre un type défini par l'utilisateur permutable consiste à fournir un échange de fonction non membre dans le même espace de noms que le type: voir Échangeable pour plus de détails.

Toute lvalue ou rvalue de ce type peut être échangé avec une lvalue ou rvalue d'un autre type, en utilisant l'appel de fonction non qualifiée swap() dans le contexte où les deux std::swap et les swap() définis par l'utilisateur s sont visibles.

+0

Ok merci bel exemple. – FlashMcQueen

6

La citation complète est

D'abord, n'est pas considérée comme la recherche en fonction de l'argument si l'ensemble de recherche produit par consultation non qualifiée habituelle contient les éléments suivants:

  1. une déclaration de un membre de classe
  2. une déclaration d'une fonction à la portée de bloc (ce n'est pas une déclaration d'utilisation)
  3. toute déclaration t Ce n'est pas une fonction ou un modèle de fonction (par ex.un objet de fonction ou d'une autre variable dont les conflits nom avec le nom de la fonction qui est examiné jusqu'à)

Ce que cela signifie est que l'ADL est ignorée que lorsque produit recherche non qualifié l'un des trois résultats ci-dessus. Puisque nous ne traitons pas avec un membre de la classe, la fonction est déclarée à la portée de l'espace de noms, pas à la portée du bloc, et nous ne trouvons que les fonctions sur lesquelles nous continuons à utiliser ADL.

+0

Alors qu'est-ce qu'une déclaration d'une fonction à l'étendue de bloc signifie (la déclaration est dans la portée courante?) – FlashMcQueen

+0

@FlashMcQueen C'est une fonction qui est déclarée à [bloc scope] (http://en.cppreference.com/w/cpp/language/scope # Block_scope) – NathanOliver