Mit auto und decltype, um eine Retouren-aus-Funktion in einer Vorlage gebildete Klasse
Wie kann ich mich zwingen, eine Funktion in eine vorgefertigte Klasse für die Rückgabe einer Referenz auf eine Membervariable mit auto/decltype?
Hier verharmlost Beispiel, was ich versuche zu tun. Angenommen, du hast eine vorgefertigte Klasse, die speichert etwas in eine private member-variable, a_
wie folgt:
#include <iostream>
template <typename T>
class A
{
private:
T a_;
public:
A(T a) : a_(a) {}
//1. Return const reference to a_
const T & get() const { return a_; }
//2. Return non-const reference to a_
T & get() { return a_; }
};
int main(int argc, char *argv[])
{
A<int> a(3);
const auto & a1 = a.get(); //1. Return const reference to a_
//a1 = 4; //Shouldn't compile
std::cout << "Value of a = " << a.get() << std::endl;
auto & a2 = a.get(); //2. Return non-const reference to a_
a2 = 5;
std::cout << "Value of a = " << a.get() << std::endl;
return 0;
}
Die erwartete/gewünschte Ausgabe:
Value of a = 3
Value of a = 5
Aber nun, angenommen, ich möchte die compiler, Rückschlüsse auf die Art zurückgegeben, die von const und non-const get()
Funktionen in A<T>
und ich möchte sicherstellen, dass beide Aufrufe geben Referenzen zu a_
.
Meine beste Vermutung ist derzeit:
template <typename T>
class A
{
private:
T a_;
public:
A(T a) : a_(a) {}
//1. Return const reference to a_
const auto get() const -> std::add_lvalue_reference<const decltype(a_)>::type
{
return a_;
}
//2. Return non-const reference to a_
auto get() -> std::add_lvalue_reference<decltype(a_)>::type
{
return a_;
}
};
aber, dass nicht kompiliert werden kann. Die ersten Fehler gegeben, die von GCC ist:
decltype.cpp:11:29: error: expected type-specifier
decltype.cpp:11:26: error: expected ‘;’ at end of member declaration
decltype.cpp:11:29: error: ‘add_lvalue_reference’ in namespace ‘std’ does not name a type
Die motivation für diese liegt außerhalb meiner destilliertem Beispiel-code, sondern ergibt sich aus einem Versuch, reduzieren die Anzahl der Parameter eine Vorlage nimmt, wenn eine (oder mehrere) dieser Parameter wird nur verwendet, um anzugeben, eine Rückkehr geben, die der compiler sollte (glaube ich) in der Lage sein, um daraus von selbst. Hinweis: in der realen Welt, ist der Rückgabetyp von get()
ist nicht, dass der a_
, aber ist der return-Typ von Funktion f(a_)
was weiß ich zu sein, ableitbar durch den compiler. Daher mein Bedürfnis für auto/decltype in diesem Beispiel.
Die Sache, die mir rätselhaft ist, dass der compiler ableiten kann, ist der Rückgabetyp korrekt mit fast identischer code in einer nicht-Vorlagen-Klasse:
class A
{
private:
int a_;
public:
A(int a) : a_(a) {}
//1. Return const reference to a_
const auto get() const -> std::add_lvalue_reference<const decltype(a_)>::type
{
return a_;
}
//2. Return non-const reference to a_
auto get() -> std::add_lvalue_reference<decltype(a_)>::type
{
return a_;
}
};
Jede Hilfe zu verstehen, was mir fehlt, sind sehr willkommen.
Details:
Centos 6.5
gcc (GCC) 4.7.2 20121015 (Red Hat 4.7.2-5)
- Sie müssen
typename
const auto get() const
Für eine trailing-return-Typ, verwenden Sie nurauto
vor den Funktionsnamen, nichtconst auto
.- Sind Sie sicher? Es funktioniert, wenn ich hinzufügen
typename
wo Sie benötigt wird. - Das ist es, was das Geräusch erklärt. Ich kann schauen die Grammatik..
- Sieht aus wie dyp ist korrekt - [dcl.spec.auto] Die
auto
unddecltype(auto)
Typ-Spezifizierer bestimmt eine Art Platzhalter, die ersetzt werden, später, entweder direkt oder durch Abzug von einer Initialisierung oder durch explizite Angabe mit einem trailing-return-Typ. Beide gcc und VS2013 akzeptierenconst auto
ohne Beschwerden obwohl. - Ich denke, dass der Absatz nicht direkt verbieten, mit
const auto
, denn es gilt auch für Deklarationen von Variablen (auto
ersetzt wird). Achten Sie jedoch auf [dcl.fct]/2, die es verbietet ausdrücklich - 8.3.5[dcl.fct]/p2 sagt: "In einer Erklärung
T D
woD
hat die form [Grammatik für die Funktionsdeklaration mit trailing return type]T
werden die einzelnen type-specifierauto
." - Genau. Etwas Zeit für die bug-reports.
- und dyp: ja, ich lese die gleiche Sache. Aber was ist abgeleitet Deklarator-Typ-Liste? 🙂
- Ähhh wenn ich mich Recht erinnere ist dies definiert jedes mal, wenn es erwähnt wird (D. H., es ist eine sinnlose transparente alias)
- stackoverflow.com/questions/13779273/...
- Ich hätte erwartet [dcl.spec.auto] zu sagen, Optional cv-qualifiziert, wenn es erlaubt war, sich dann aber wieder die Sektion wies darauf hin, von TC nicht sagen nichts über
decltype(auto)
es könnte also ein Fehler sein. - Danke.
- Gut [dcl.spec.auto] nicht implizit erlauben Lebenslauf-Qualifikationen; [dcl.fct]/2 erfordert die Verwendung eines trailing-return-Typ, der kann nicht kombiniert werden mit
decltype(auto)
. - BTW
// 1. Return const reference to a_
ist falsch, es gibt einen Verweis aufa_
die gebunden ist in eine const-Referenz. - Als Klarstellung für alle Besucher, die
const auto
ist es nicht notwendig, in diesem Zusammenhang ohnehin, anders als bei Variablen-Deklarationen mitauto
-, Funktions-auto hat halten cv-Qualifikation.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Nur um es zu erwähnen, Sie haben tatsächlich nicht zu verwenden
std::add_lvalue_reference
um das Verhalten, die Sie wollen. Das funktioniert genauso gut und ist besser lesbar in meinem Buch.Wrap
a_
in ein zusätzliches paar von Klammern in der trailing return type, um den Typ des Ausdrucksa_
statt des deklarierten Typs der variablea_
(Live at Coliru):oder wenn C++1y verfügbar ist:
auto& get() const { return a_; }
werdenconst auto& get() const { return a_; }
wenn Sie wollen, um wieder eine const-Referenz? Das const nach dem Funktionsnamen bedeutet, dass Sie rufen Sie die Memberfunktion auf einem Konstanten Objekt es gehört.auto&
ableiten kann, eine Referenz auf const-Typ nur in Ordnung.const auto&
wäre in diesem Fall nicht mehr richtig ist, nur deutlicher.