Pytanie Dlaczego unique_ptr nie może określić typu deletera?


Powiedzmy, że chcę użyć niestandardowego deltera z unique_ptr:

void custom_deleter(int* obj)
{
    delete obj; 
}

Dlaczego muszę to napisać:

std::unique_ptr<int, void(*)(int*)> x(new int, custom_deleter);

zamiast tego:

std::unique_ptr<int> x(new int, custom_deleter); //does not compile

?

Czy nie można wywnioskować typu deletera?


11
2018-04-15 20:35


pochodzenie


Związane z: stackoverflow.com/questions/21355037/... - 0x499602D2
Klasy szablonów nie określają parametrów szablonu. Działają tylko funkcje szablonu. - Cássio Renan
zastanawiam się dlaczego std::make_unique nie ma przeciążenia, w którym można określić deleter. W ten sposób możesz określić typ deletera. - vsoftco
@vsoftco Patrzyłem właśnie na dokumenty i zastanawiałem się nad tym samym ... - Cássio Renan
@vsoftco Jak to działa? Musi wziąć pakiet argumentów do skonstruowania T. Jak byś rozróżnił, który z nich Args... jest Deleter? - Barry


Odpowiedzi:


Dla unique_ptr, deleter jest częścią typu:

template <
    class T,
    class Deleter = std::default_delete<T>
> class unique_ptr;

W związku z tym, podczas konstruowania obiektu, musisz określić jego typ. Linia, którą piszesz:

std::unique_ptr<int> x(new int, custom_deleter);

jest równa:

std::unique_ptr<int, std::default_delete<int> > x(new int, custom_deleter);

I nie możesz zbudować std::default_delete<int> od custom_deleter.

Jedyny sposób wywnioskować Typ deletera ma również korzystać z odliczania szablonów na tej części:

template <typename T, typename Deleter>
std::unique_ptr<T, Deleter> make_unique_ptr(T* ptr, Deleter deleter) {
    return std::unique_ptr<T, Deleter>(ptr, deleter);
}

6
2018-04-15 20:48



właśnie to bym zrobił std::make_unique, nie widzę żadnego powodu, dla którego nie zostałby tak zaimplementowany. - vsoftco
@vsoftco [skopiowane z góry] Jak to działałoby? Musi wziąć pakiet argumentów, aby zbudować T. Jak byś rozróżnił, który z Argów ... jest Deleterem? - Barry
może z a std::piecewise_construct / std::forward_as_tuple - vsoftco


Nie można wnioskować o rodzaju deletera, ponieważ unique_ptr domyślnie nie ma stanu poświęconego deleterowi: domyślny deleter jest bezstanowy.

W twoim przypadku deleter potrzebuje wartości wskaźnika, więc nie może się "dopasować" do std::unique_ptrstan (który jest tylko wskaźnikiem do T).

To sprawia unique_ptr lekki, prawie darmowy zamiennik dla posiadanego wskaźnika.

Deductin można by zrobić, ale musiałby zmienić rodzaj powstałego unique_ptr.

W porównaniu, shared_ptr zawsze ma pojemność stanów dla deletera, dwa różne liczniki atomowe i wskaźnik do wartości. Jest to większa waga, a nie kosztowny zamiennik wskaźnika.


3
2018-04-16 02:51