2013-07-07 15 views
8

Ich habe folgendes Testprogramm nicht bindend:Temporäre const Array rvalue Referenz

#include <iostream> 
#include <type_traits> 
#include <utility> 

template<typename Ty, std::size_t N> 
void foo(Ty (&&)[N]) 
{ 
    std::cout << "Ty (&&)[" << N << "]\t" << std::is_const<Ty>::value << '\n'; 
} 

template<typename Ty, std::size_t N> 
void foo(Ty (&)[N]) 
{ 
    std::cout << "Ty (&)[" << N << "]\t" << std::is_const<Ty>::value << '\n'; 
} 

template<typename Ty> 
using id = Ty; 

int main() 
{ 
    std::cout.setf(std::cout.boolalpha); 

    foo(id<int[]>{1, 2, 3, 4, 5}); 
    foo(id<int const[]>{1, 2, 3, 4, 5}); // <-- HERE. 
    int xs[]{1, 2, 3, 4, 5}; 
    foo(xs); 
    int const ys[]{1, 2, 3, 4, 5}; 
    foo(ys); 
    foo(std::move(xs)); 
    foo(std::move(ys)); 
} 

Ich würde erwarten, dass die Linie mit einem Pfeil markiert würde gerade über die R-Wert Überlastung wie der nicht-const Anruf nennen, aber es tut es nicht.

Ist das nur ein Fehler in GCC oder gibt es etwas im Standard, das die Lvalue-Überladung verursacht?

+0

Interessant, Clang wird das richtig und ruft die Rvalue-Überladung auf. – Xeo

+0

Gute Frage: Mein naives Verständnis des Standards stimmt mit Ihrem überein. [Live] (http://ideone.com/ErHuYO), wenn Sie die Ausgabe sehen möchten. – Yakk

+0

Etwas lustiges geht hier: http://ideone.com/ptTJ8i - mein 'const int' temporäres wird wie ein' int && 'behandelt, nicht ein' const int && '. – Yakk

Antwort

2

nach der Norm §12.2 [class.temporary]:

Provisorien der Klasse Art sind in verschiedenen Kontexten erstellt: Binden eine Bezugnahme auf eine prvalue (8.5.3), Zurückgeben einen prvalue (6.6.3), ein Konvertierung, die einen Prvalue erzeugt (4.1, 5.2.9, 5.2.11, 5.4), eine Ausnahme (15.1), einen Handler (15.3) und in einigen Initialisierungen (8.5) werfen.

So ist id<int const[]>{1, 2, 3, 4, 5} eine temporäre und daher ist ein prvalue §3.10 [basic.lval]:

rvalue (so genannt, historisch, weil rvalues ​​auf die rechte Seite eines Zuweisungsausdruck erscheinen könnte) ist ein xvalue, ein temporäres Objekt (12.2) oder Unterobjekt davon oder ein Wert, der nicht zugeordnet ist.

Ein Prvalue ("reiner" R-Wert) ist ein R-Wert, der kein x-Wert ist.

Daher soll überladen Funktion mit Rvalue Referenzargument ausgewählt werden.

+0

Also im Grunde ist es ein Fehler in GCC? – Mehrdad

+0

@Mehrdad: Ich nehme an, es ist. Wie Xeo in seinem Kommentar sagte, bekommt Clang das richtig. –