86 votes

Pourquoi ne pas ADL trouver les modèles de fonction?

Quelle partie du C++ spécification limite l'argument de référence dépendant de trouver les modèles de fonction dans l'ensemble des associés des espaces de noms? En d'autres termes, pourquoi le dernier appel en main - dessous ne parviennent pas à compiler?

namespace ns {
    struct foo {};
    template<int i> void frob(foo const&) {}
    void non_template(foo const&) {}
}

int main() {
    ns::foo f;
    non_template(f); // This is fine.
    frob<0>(f); // This is not.
}

88voto

Kornel Kisielewicz Points 26556

Cette partie explique:

Norme C++ 03 14.8.1.6:

[Note: Pour de simples noms de fonction, l'argument dépendante de recherche (3.4.2) s'applique même lorsque le nom de la fonction n'est pas visible dans le champ d'application de l'appel. C'est parce que l'appel a encore la forme syntaxique d'un appel de fonction (3.4.1). Mais quand un modèle de fonction explicite arguments de modèle est utilisé, l'appel n'a pas la bonne forme syntaxique, sauf s'il existe un modèle de fonction de même nom visible au moment de l'appel. Si aucun nom n'est visible, l'appel n'est pas syntaxiquement bien formées et argument-dépendante de recherche ne s'applique pas. Si certains de ces nom est visible, l'argument dépendante de recherche s'applique et supplémentaires, les modèles de fonction peut être trouvé dans d'autres espaces de noms.

namespace A {
  struct B { };
  template<int X> void f(B);
}
namespace C {
  template<class T> void f(T t);
}
void g(A::B b) {
  f<3>(b);    //ill-formed: not a function call
  A::f<3>(b); //well-formed
  C::f<3>(b); //ill-formed; argument dependent lookup
              // applies only to unqualified names
  using C::f;
  f<3>(b);    //well-formed because C::f is visible; then
              // A::f is found by argument dependent lookup
}

0voto

Troubadour Points 9485

Edit: Non, ce n'est pas juste. Voir @Kornel de réponse.


Je ne suis pas entièrement sûr, mais après avoir consulté de Stroustrup "Le langage de programmation C++" je pense que l'Annexe C section 13.8.4 pourrait en être la cause.

Depuis frob est un modèle, on pourrait éventuellement se spécialiser pour i=0 à un point après que vous l'appelez. Cela signifie que la mise en œuvre serait de gauche avec les deux façons possibles de choisir frob d'appel tel qu'il apparaît, il peut choisir au moment de l'instanciation ou à la fin du traitement de l'unité de traduction.

Donc, je pense que le problème est que vous pourriez faire

namespace ns {
    struct foo {};
    template<int i> void frob(foo const&) {}
}

int main() {
    ns::foo f;
    frob<0>(f);
    return 0;
}

namespace ns {
    template<> void frob< 0 >(foo const&) { /* Do something different*/ }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X