decltype für die Variable des Referenztyps mit geschweiften Klammern

Dec 15 2020

Betrachten Sie den folgenden Code :

#include <type_traits>

int main() {
    const int& p = 42;
    auto v1 = decltype(p){};
    static_assert(std::is_same_v<decltype(v1), int>);
    
    decltype(p) v2{};
    static_assert(std::is_same_v<decltype(v2), const int&>);
    // auto v3 = X(const int&)X {};
}

Art von v1wird abgeleitet als int. Gleichzeitig wird der Typ von v2voraussichtlich als abgeleitet const int&. Ich denke, der erste Schritt für v1könnte so behandelt werden, dass ein weiterer Typ-Alias ​​hinzugefügt wird using T = decltype(p);und dann auto v4 = T{};. Wie wird dieser Ausdruck ( decltype(p){}oder T{}) vom Compiler behandelt? Ich weiß, dass dieser {}Teil zur Instanziierung dient, aber wie ist der resultierende Typ von v1kein Referenztyp?

Noch eine Frage: Gibt es eine Möglichkeit, v3Variablen desselben Typs zu deklarieren , die v1explizit notierten Typ const int&(anstelle von decltype(p)) verwenden?

Alle Links zu Standard wäre dankbar.

Antworten

1 Enlico Dec 15 2020 at 00:48

(An die Downvoter: Wenn Sie downvotiert haben, weil Sie denken, dass das Zitieren von Scott Meyers nicht gleichbedeutend mit dem Zitieren des Standards ist, na ja ...)

Wie Sie aus Effective Modern C ++ lesen können (ergänzt durch den Teil der Errata , den Sie durch Suchen Case 2:unter diesem Link erreichen können, und das vereinfacht das Lesen nur, ist aber für die Frage nicht wesentlich):

Wenn ParamTypees sich um eine [...] Nichtreferenz handelt expr, wenn der Typ eine Referenz ist, ignorieren Sie den Referenzteil. Wenn [...], exprist das constauch wichtig. Wenn volatileja, ignorieren Sie das auch.

Wo paramist der Deklarationsspezifizierer, der in Ihrem Fall gerecht ist auto, dh eine Nichtreferenz.

Mit anderen Worten, Sie erstellen v1über Plain auto(nicht auto&), dh per Kopie. Es spielt also keine Rolle, ob Sie es mit einer Entität initialisieren, die referenziert ist oder nicht, oder sogar mit constoder nicht (oder volatileoder nicht, fwiw). weil du es kopierst.

Denken Sie an den einfacheren Fall,

int i = 3;
int& p = i;
auto v1 = p;

Für ihn v1ist es wirklich nicht wichtig, ob er mit dem einen ( i) oder dem anderen ( p) Namen initialisiert ist, unter dem dieselbe Entität bekannt ist, da er eine Kopie des Wertes erhält, den diese Entität hat.

autoDer Typabzug funktioniert genauso wie der Typabzug von Vorlagen (mit Ausnahme eines Unterschieds im Umgang mit dem geschweiften Initialisierer, der in diesem Fall nicht relevant ist), und für beide können Sie sich auf Scott Meyers ' Effective Modern C ++ beziehen .