2014-03-07 10 views
9

Für den folgenden Code:Überlastauflösung mit Universal-Referenz beteiligt

class A {}; 

template <typename T> void f(T& a) {} 
template <typename T> void f(T&& a) {} 

int main() { 
    A a; 
    f(a); 
} 

Klirren ++ bindet den Anruf an die erste Überlast, während g ++ mehrdeutig Anruf berichtet. Wer macht die richtige Handlung?

Antwort

6

Sowohl gcc 4.9.0 20140302 als auch clang 3.5 (trunk 202594) wählen die erste Version korrekt aus. Als hvd gab mir freundlicherweise the references in comments:

Wenn für einen bestimmten Typen, gelingt es Abzug in beiden Richtungen (dh die Typen nach den Transformationen obigen identisch sind), und beide P und A waren Referenztypen (bevor sie mit der oben genannten Art ersetzt werden):
- Wenn der Typ aus der Argumentvorlage eine lvalue-Referenz und der Typ aus der Parametervorlage nicht war, wird der Argumenttyp als spezialisierter angesehen als der andere; andernfalls
- Wenn der Typ aus der Argumentvorlage mehr cv-qualifiziert ist als der Typ aus der Parametervorlage (wie oben beschrieben), wird der Argumenttyp als spezialisierter angesehen als der andere; ansonsten
- keiner der beiden Typen ist spezialisierter als der andere.


By the way, sehen The Universal Reference/Overloading Collision Conundrum Video, warum auf dem Universal-Referenzen Überlastung ist eine schlechte Idee. Kurz gesagt, betrachten Sie das folgende Beispiel:

#include <iostream> 
#include <utility> 

struct A { bool guts_stolen; }; 

void steal_guts(A&& a) { 
    a.guts_stolen = true; 
} 

template <typename T> void f(const T& a) { 
          // ^^^^^ note the const! 
    std::cout << "T&\n"; 
} 

template <typename T> void f(T&& a) { 
    std::cout << "T&&\n"; 
    steal_guts(std::move(a)); 
} 

int main() { 
    A a{ false }; 
    f(a); 
    std::cout << "Guts stolen? " << std::boolalpha << a.guts_stolen << std::endl; 
} 

Wenn Sie das Programm ausführen, wird es

T&& 
Guts stolen? true 

drucken, die überhaupt nicht das, was Sie durch einen Blick auf A a{ false }; f(a); nur erwarten würde.

+0

Sowohl die erste Version, mit 'T = A', als auch die zweite Version, mit' T = A & ', haben einen Parameter vom Typ' T & ', also auf welcher Basis kann man sagen, dass es richtig ist die erste Version wird ausgewählt? (Ich denke, du hast Recht, aber du solltest deine Antwort wirklich erklären.) – hvd

+0

@hvd Ja, ich versuche den entsprechenden Abschnitt im Standard zu finden/ein gcc Bugreport in Bugzilla. – Ali

+1

[Hier] (http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1164) und [hier] (http://gcc.gnu.org/bugzilla/show_bug. cgi? id = 57172) :) – hvd

Verwandte Themen