Pytanie std :: unique_ptr constexpr constructors


Jak pokazano tutaj, std::unique_ptr ma dwa constexpr konstruktory dla wskaźników zerowych:

constexpr unique_ptr();
constexpr unique_ptr( nullptr_t );

Mam dwa pytania do tych dwóch konstruktorów:

  1. Dlaczego potrzebujemy dwóch? Czy nie możemy po prostu zadeklarować jednego jako:

    constexpr unique_ptr( nullptr_t = nullptr );
    
  2. Jest constexpr naprawdę użyteczne? Próbowałem to zrobić w moim kodzie, ale nie skompilowałem (g ++ 6.1.0, -std=c++14):

    constexpr std::unique_ptr<int> p;
    // error: the type 'const std::unique_ptr<int>' of constexpr variable 'p'
    // is not literal because 'std::unique_ptr<int>' has a non-trivial destructor
    

14
2017-07-23 06:23


pochodzenie


Wiąże się to z tym samym pytaniem - Dutow
@Dutow Hahahaha - Zizheng Tai
Błąd kopiowania / wklejania LOL. Ale odpowiedź oldrinba łączy się z tą, którą miałem zamiar połączyć. - T.C.


Odpowiedzi:


Dla (1), uważamy, że zapewnia on zarówno konstruktor no-arg unique_ptr() i konstruktor zerowy-wskaźnik unique_ptr(nullptr_t) mają takie same gwarancje na czas kompilacji, tj. oba są constexpr. Widzimy różnicę w §20.8.1.2:

constexpr unique_ptr() noexcept;
explicit unique_ptr(pointer p) noexcept;
...
constexpr unique_ptr(nullptr_t) noexcept
: unique_ptr() { }

Dlaczego te dwa nie zostały połączone w jeden konstruktor z wartością domyślną jest prawdopodobne historyczne przygodności.

W odniesieniu do (2), dlaczego powinniśmy się tym przejmować constexpr pomimo nietrywialnego destruktora, rozważ odpowiedź tutaj podana:

constexpr konstruktory mogą być używane do ciągłej inicjalizacji, która, jako forma statycznej inicjalizacji, jest gwarantowana, zanim nastąpi inicjalizacja dynamiczna.

Na przykład, biorąc pod uwagę globalne std::mutex:

std::mutex mutex;

W zgodnej implementacji (czytaj: nie MSVC) konstruktorzy innych obiektów mogą bezpiecznie blokować i odblokowywać mutex, becuase std::mutexKonstruktorem jest constexpr.


14
2017-07-23 06:43





Co do Q1, nullptr_t Konstruktor został dodany później w N2435, po pierwotnym wniosku (N1586).

Dodanie prostego przeciążenia, które można określić w jednym wierszu, jest znacznie czystsze niż próba bycia sprytnym, szczególnie, że [member.functions] pozwala już implementacji na użycie "sprytnej" wersji, jeśli chcą.


9
2017-07-23 07:01



Zatem obecni dwaj lekarze określeni w standardzie powinni być funkcjonalnie równoważni temu z mojego pytania, prawda? - Zizheng Tai