2016-06-21 10 views
7

This page sagt, dass die make_optional Funktion in C++ 17 eine constexpr optional<...> zurückgibt. Ich denke (ich könnte mich aber irren) das würde erfordern, dass optional<T> einen constexpr Kopierer oder Move Konstruktor hat. Allerdings sagt this page auch, dass das nicht der Fall ist.C++ 17 make_optional conexpr-

Ich weiß nicht, wie make_optional implementiert werden kann, wie der C++ 1Z Entwurf derzeit steht. Siehe this post zur Verdeutlichung. Gibt es eine Workaround, oder ist es nur der Standard-Entwurf/cppreference Fehler?

+0

Es gibt keine Frage in dieser Frage. – immibis

+0

@immibis Aktualisiert :) –

+1

cppreference hat das 'constexpr' nicht aus der Luft gezaubert, weißt du ... –

Antwort

2

Dank @Yakk und @ T.C. für ihre Erklärungen. Ich fühle mich ein Beispiel sollte die Dinge klarer machen:

struct wrapper { 
    int value; 

    // non-explicit constexpr constructor 
    constexpr wrapper(int v) noexcept : value(v) {} 

    // non-constexpr copy & move constructors 
    wrapper(const wrapper& that) noexcept : value(that.value) {} 
    wrapper(wrapper&& that) noexcept : value(that.value) {} 
}; 

constexpr wrapper make_wrapper(int v) 
{ 
    return {v}; 
} 

int main() 
{ 
    constexpr auto x = make_wrapper(123); // error! copy/move construction, 
              // but no constexpr copy/move ctor 

    constexpr int y = make_wrapper(123).value; // ok 
    static_assert(y == 123, "");    // passed 
} 

So make_wrapper erfolgreich ein constexpr wrapper zurückkehrt; Es ist die Copy/Move-Konstruktion (obwohl sie normalerweise von Compilern unterstützt wird), die die Kompilierung des Codes verhindert, da es keinen constexpr Copy/Move-Konstruktor gibt.

Wir können die constexpr -ness des zurückgegebenen (temporären) wrapper Objekts überprüfen, indem Sie seinen Elementwert verwenden, um eine constexpr Variable zu initialisieren.

1

Sie können Rückgabewerte in C++ 11 mit return {something}; direkt konstruieren. Wenn es nicht explizite Ctors gibt, die constexpr sind, können Sie es aus einer Funktion zurückgeben.

+0

Ich glaube, das ist eine Illusion, die durch Kopier-Elision verursacht wird. Ohne copy-elision wird es nicht kompiliert: [gcc] (https://godbolt.org/g/X3pTzv), [clang] (https://godbolt.org/g/AiqxxV). –

+0

Und wie die Antworten in meinem verlinkten Post erwähnt, auch wenn der Compiler Kopier-Elision ausführt, muss ein "constexpr" -Kopie/Move-Konstruktor immer noch zugänglich sein (auch wenn es schließlich nicht verwendet wird). –

+0

@ZizhengTai Es ist dein eigenes Beispiel, dass es eine neue Kopie erstellt. https://godbolt.org/g/jT7mHd Copy-list-initialization erstellt keine provisorischen oder konzeptionellen Provisorien. –