2014-06-30 11 views
11

Folgende funktioniert gut (wie man erwarten würde):Template-Umwandlungsfunktion zu konst Verweis

struct X {}; 

struct A 
{ 
    operator X const&() 
    { 
    static const X value{}; 
    return value; 
    } 
}; 

int main() 
{ 
    A a; 
    X x = a; 
} 

Aber das ist nicht so klar:

template<typename T> 
struct X {}; 

struct A 
{ 
    template<typename T> 
    operator X<T> const&() 
    { 
    static const X<T> value{}; 
    return value; 
    } 
}; 

int main() 
{ 
    A a; 
    X<int> x = a; 
} 

GCC 4.9 sagt error: conversion from ‘A’ to non-scalar type ‘X<int>’ requested während Klirren 3.4 hat keine Probleme damit. Wenn Sie die const oder die & aus der Konvertierungsfunktion entfernen oder wenn Sie X<int> const &x = a schreiben, dann ist GCC auch glücklich.

So findet GCC die Konvertierungsfunktion nur dann nicht, wenn der Zieltyp eine const & zu einer Vorlagenklasse ist und Sie eine Konvertierung in ein nicht const & Objekt dieser Klasse anfordern. Ist das das richtige Verhalten? Ich habe versucht, den Standard zu lesen, aber die Überladungsregeln sind ziemlich verwirrend für mich.

Antwort

5

Ja, das ist ein Fehler in gcc. Dies ist fast genau core DR976, der einzige Unterschied, dass der Zieltyp in ihrem Beispiel zu sein, ist ein nicht-Klasse Typ:

struct F { 
    template<class T> 
    operator const T&() { static T t; return t; } 
}; 

int main() { 
    F f; 
    int i = f; // ill-formed 
} 

Wie bei Ihrem Beispiel Klirren akzeptiert und gcc lehnt dieses Beispiel, und zwar unabhängig von der Standardversion Dialekt ausgewählt.

Beachten Sie, dass die von dieser DR geändertene Klausel (14.8.2.3 [temp.deduct.conv]) unterscheidet nicht zwischen Klasse und nicht-Klasse Zieltypen, so dass die Auflösung des DR gleiche Weise für Ihren Code gilt.

Per geänderten Klausel 14.8.2.3, der Compiler sollte:

  • bestimmen P, der Rückgabetyp der Konvertierungsfunktion Vorlage, wie X<T> const & und A, das gewünschte Ergebnis-Typ, wie X<int>;
  • Streifen Sie die Referenz von P, geben X<T> const;
  • Streifen die cv-Qualifikation von P, geben X<T>;
  • leiten T als int ab.

Ich würde empfehlen, einen Fehlerbericht auf https://gcc.gnu.org/bugzilla/, der darauf verweist, dass DR.


Da in Ihrem Fall, dass Sie zu einem Klasse-Typ konvertieren, ist es eine Abhilfe zur Verfügung:

X<int> x1 = a;   // fails 
X<int> x2(a);   // OK 
X<int> x3 = X<int>(a); // also OK 

In Direkt Initialisierung werden Konstrukteure des Zieltypen betrachtet (8.5p16); Der Standard-Kopierkonstruktor von X<int> benötigt einen Parameter vom Typ X<int> const&, zu dem, wie wir bereits gesehen haben, gcc gerne a konvertiert.

+0

Dank Ihrer guten Erklärung und dem Link zum Fehlerbericht habe ich einen Fehlerbericht eingereicht: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61663 –

Verwandte Themen