Pytanie Dlaczego ten skompilowany kod C ++ nie powoduje przeciążenia kodu / przestrzeni nazw / szablonu?


Oto trochę kodu C ++:

namespace A {

int f(int x) { return 0; }
int f(long x) { return 1; }

template<class T> int g(T x) {
  return f(x);
}

}

namespace B {
struct C {};
}

namespace A {
int f(B::C x) { return 2; }
}

void h() {
  A::g(B::C());
}

W przestrzeni nazw A kod deklaruje kilka przeciążeń funkcji f oraz funkcję szablonu, która wywołuje f. Następnie deklarujemy nowy typ w przestrzeni nazw B i przeciążenie f dla nowego typu w przestrzeni nazw A. Kompilacja z g ++ 4.2 daje

order.cpp: In function ‘int A::g(T) [with T = B::C]’:
order.cpp:21:   instantiated from here
order.cpp:7: error: no matching function for call to ‘f(B::C&)’
order.cpp:3: note: candidates are: int A::f(int)
order.cpp:4: note:                 int A::f(long int)

Kod działa, jeśli wykonuję jedną z następujących czynności:

  1. Usuń przestrzenie nazw.
  2. Przenieś przeciążenie f dla B :: C do przestrzeni nazw B (dzięki wyszukiwaniu Koeniga).
  3. Przenieś deklarację B :: C i jej przeciążenie powyżej definicji g ().

Jestem szczególnie zaintrygowany (3), ponieważ miałem wrażenie, że rozdzielczość przeładowania powinna być niezależna od kolejności deklaracji. Czy to oczekiwane zachowanie w C ++?


12
2017-12-02 22:59


pochodzenie


To wspaniałe pytanie, a oto trzy uproszczone przykłady tego samego: 1) zawiedzie: ideone.com/MSQHk 2) usuń int f(int); i kompiluje: ideone.com/W1jZA 3) przenieś szablon do góry i ponownie go skompiluj: ideone.com/zbedP - Gene Bushuyev
Robi się jeszcze ciekawiej. Wygląda na to, że gcc 4.5.1 również nie jest bez błędów. Comeau odrzuca zarówno 2), jak i 3) przykłady, a także gdy jest umieszczony w globalnej przestrzeni nazw, ale znajduje f w B z ADL. - Gene Bushuyev
Co ciekawe, kod kompiluje się i działa dobrze w MSVS 2010. - James Leonis


Odpowiedzi:


Clang daje następujący komunikat o błędzie, który daje pewne wskazówki dotyczące problemu:

$ clang -fsyntax-only test.cc -Wall
test.cc:7:10: error: call to function 'f' that is neither visible in the
      template definition nor found by argument-dependent lookup
  return f(x);
         ^
test.cc:21:3: note: in instantiation of function template specialization
      'A::g<B::C>' requested here
  A::g(B::C());
  ^
test.cc:17:5: note: 'f' should be declared prior to the call site or in
      namespace 'B'
int f(B::C x) { return 2; }
    ^
1 error generated.

W szczególności natknąłeś się na szczegół dwuetapowego wyszukiwania nazw zależnych w definicjach szablonów. W C ++ 98, [temp.dep.candidate] mówi:

W przypadku wywołania funkcji, które zależy od parametru szablonu, jeśli nazwa funkcji jest niekwalifikowanym identyfikatorem, ale nie jest identyfikatorem szablonu, funkcje kandydujące można znaleźć przy użyciu zwykłych reguł wyszukiwania (3.4.1, 3.4.2), z tym że:

  • Dla części wyszukiwania przy użyciu nieokreślonego wyszukiwania nazwy (3.4.1) znajdują się tylko deklaracje funkcji z zewnętrznym powiązaniem z kontekstu definicji szablonu.
  • W przypadku części wyszukiwania przy użyciu powiązanych przestrzeni nazw (3.4.2), znaleziono tylko deklaracje funkcji z zewnętrznym powiązaniem w kontekście definicji szablonu lub kontekście tworzenia instancji szablonu.

Od A::f(B::C x) nie znaleziono przy użyciu powiązanych przestrzeni nazw (tj. wyszukiwania zależnego od argumentu), musi być widoczny na stronie definicji szablonu, a nie tylko w miejscu tworzenia instancji.


6
2017-12-15 07:44





Na przykład

int f(int x) { return 0; }
int f(long x) { return 1; }

funkcje nie są funkcjami szablonu (tj. nie mają template <class T> przed nimi. T jest parametrem szablonu). Dlatego można je skompilować w locie po osiągnięciu kodu szablonu.


0
2017-12-02 23:32



To nie ma znaczenia. Zostaną one skompilowane w każdym razie. Pytanie brzmi, w jaki sposób kompilator powinien rozwiązać połączenie g. - UncleBens
@UncleBens: (Komentując tutaj, ponieważ moja odpowiedź została usunięta): Masz rację, byłem zbyt uproszczony w moim zrozumieniu. Usunąłem odpowiedź, ponieważ jest ona błędna, ale nie mam czasu na resztę dnia, aby ją naprawić, więc prosimy o hi-jack i popraw to jako własne. :) - GManNickG
@UncleBens: Ktoś prosił o wyjaśnienie "wszystkiego, co nie jest szablonem". Dlatego dodałem tę odpowiedź, choć wydaje się, że komentarz został usunięty. - Furkan Kıraç