2017-09-20 3 views
1

je suis tombé sur l'exemple suivant confusion impliquant ADL et les fonctions supprimées:Fonction supprimée et ADL

Premier exemple:

namespace A 
{ 
    struct S{}; 

    void f(S){cout << "adl" << endl;} 
} 

namespace C 
{ 
    //void f() = delete; 

    //void f (double); 

    void test() 
    { 
     A::S arg; 
     f(arg); 
    } 
} 


int main() 
{ 
    C::test(); 

    return 0; 
} 

Comme prévu, A::f est appelé par ADL. Dans l'exemple suivant, il y a une fonction supprimée avec le même nom dans C:

namespace A 
{ 
    struct S{}; 

    void f(S){cout << "adl" << endl;} 
} 

namespace C 
{ 
    void f() = delete; 

    //void f (double); 

    void testi() 
    { 
     A::S arg; 
     f(arg); 
    } 
} 


int main() 
{ 
    C::testi(); 

    return 0; 
} 

échoue avec Compiling le message d'erreur error: use of deleted function 'void C::f()'. Apparemment, les fonctions supprimées empêchent la version ADL d'entrer dans la table de surcharge. Maintenant, pour le dernier exemple: En plus de la fonction supprimée il y a maintenant une autre, non supprimé, la fonction du même nom:

namespace A 
{ 
    struct S{}; 

    void f(S){cout << "adl" << endl;} 
} 

namespace C 
{ 
    void f() = delete; 

    void f (double); 

    void testi() 
    { 
     A::S arg; 
     f(arg); 
    } 
} 


int main() 
{ 
    C::testi(); 

    return 0; 
} 

L'exécution de cette exécute la version ADL de f. Donc, en conclusion:

  • sans fonction correspondant aux résultats d'espaces de noms en cours dans la version ADL appelés
  • Ayant juste la fonction supprimée dans les résultats de l'espace de nommage dans une erreur, probablement parce que la version ADL n'a pas été découverte à
  • Une autre fonction, non supprimée, dans l'espace de noms actuel entraîne l'appel de la version ADL.

Mes questions: Ce comportement est-il voulu? Si oui, quelle partie de la norme spécifie cela? Edit: J'ai oublié de mentionner que j'ai utilisé onlinegdb pour la compilation, donc gcc/g ++ a été utilisé.

Répondre

1

Bogue du compilateur défini. Pour citer le projet de norme C de (n4659) [dcl.fct.def.delete]/2:

Un programme qui fait référence à un implicitement ou explicitement fonction supprimé, autre que de la déclarer, est mal formé. [Note: Ceci inclut l'appel de la fonction implicitement ou explicitement et la formation d'un pointeur ou pointeur vers membre à la fonction. Il s'applique même pour les références dans expressions qui ne sont pas potentiellement évaluées. Si une fonction est surchargée, elle est référencée uniquement si la fonction est sélectionnée par résolution de surcharge. L'utilisation implicite d'une fonction virtuelle ne constitue pas, à elle seule, une référence. - note de fin]

La résolution de surcharge ne peut pas sélectionner cette surcharge par ADL. Donc, cette fonction ne devrait pas être référencée. Le deuxième exemple de code est un programme C++ bien formé (si les directives include manquantes sont remises).


Vous avez mentionné en utilisant g ++ pour compiler, notez que cette question est fixed in GCC 7.2.0

+0

Je viens de réaliser que g ++ C++ 14 5.4.1 a été utilisé dans mon exemple – LcdDrm

+1

@LcdDrm - Vous pouvez utiliser [Wandbox] (https://wandbox.org/) et faites une recherche binaire par version de GCC pour savoir exactement quand elle a été corrigée, si vous le souhaitez :) – StoryTeller

+1

GCC 6.3 échoue, GCC 7.1 fonctionne.Le compilateur MS Visual Studio fonctionne également – LcdDrm