unikalny odpowiednik PST boost?

Czy istnieje jakaś równoważna klasa dla std::unique_ptr C++1x w bibliotekach boost? Zachowanie, którego szukam, polega na tym, że mogę mieć funkcję fabryczną bezpieczną dla wyjątków, w ten sposób...

std::unique_ptr<Base> create_base()
{
    return std::unique_ptr<Base>(new Derived);
}

void some_other_function()
{
    std::unique_ptr<Base> b = create_base();

    // Do some stuff with b that may or may not throw an exception...

    // Now b is destructed automagically.
}

EDIT: w tej chwili używam tego hacka, który wydaje się najlepszym, jaki mogę uzyskać w tym momencie...

Base* create_base()
{
    return new Derived;
}

void some_other_function()
{
    boost::scoped_ptr<Base> b = create_base();

    // Do some stuff with b that may or may not throw an exception...

    // Now b is deleted automagically.
}
Author: R. Martinho Fernandes, 2010-06-01

5 answers

Nie jest możliwe stworzenie czegoś takiego jak unique_ptr bez C++0x (gdzie jest to część biblioteki standardowej, a więc Boost nie musi jej dostarczać).

W szczególności bez referencji rvalue, które są cechą w C++0x, solidna implementacja unique_ptr jest niemożliwa, z Boostem lub bez niego.

W C++03 istnieje kilka możliwych alternatyw, chociaż każda z nich ma swoje wady.

  • {[2] } jest prawdopodobnie najprostszym zamiennikiem pod względem możliwości. Ty można bezpiecznie używać go w dowolnym miejscu, w którym w przeciwnym razie użyłbyś unique_ptr i zadziałałoby. To po prostu nie byłoby tak skuteczne, ze względu na dodatkowe liczenie referencji. Ale jeśli szukasz prostego zamiennika drop-in, który jest w stanie obsłużyć wszystko unique_ptr może zrobić, to jest prawdopodobnie najlepszym rozwiązaniem. (Oczywiście, shared_ptr może zrobić o wiele więcej, ale może być również po prostu użyty jako zamiennik unique_ptr.)
  • {[7] } jest podobny do unique_ptr, ale nie pozwala na przeniesienie własności. Działa świetnie tak długo, jak długo jako inteligentny wskaźnik ma zachować wyłączną własność przez cały okres użytkowania.
  • std::auto_ptr działa bardzo podobnie do unique_ptr, ale ma kilka ograniczeń, głównie dlatego, że nie może być przechowywany w standardowych kontenerach bibliotecznych. Jeśli po prostu szukasz wskaźnika, który pozwala na przeniesienie własności, ale który nie jest przeznaczony do przechowywania w kontenerach lub kopiowania, jest to prawdopodobnie dobry zakład.
 70
Author: jalf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-01 22:36:51

Począwszy od Boost 1.57 jest oficjalna unique_ptr implementacja w Boost.Przenieś bibliotekę.

Z dokumentacji :

(...) zamiennik drop-in dla std:: unique_ptr, użyteczny również z C++03 Kompilatory.

Kod jest dostępny w pliku nagłówkowym <boost/move/unique_ptr.hpp> i mieszka w przestrzeni nazw boost::movelib. Co Więcej, Zwiększ.Biblioteka Move udostępnia funkcję fabryczną make_unique() w <boost/move/make_unique.hpp>, również w przestrzeni nazw boost::movelib.

Stąd przykład z pytania można zaimplementować w ten sposób:

#include <boost/move/unique_ptr.hpp>

using boost::movelib::unique_ptr;

unique_ptr<Base> create_base()
{
    return unique_ptr<Base>(new Derived);
}

Zobacz przykład na żywo na Wandbox. Zauważ, że kod kompiluje się dobrze z gcc 4.6.4 w trybie C++98 (!).

Co ciekawe w boost::movelib::unique_ptr W przypadku zastosowania w przypadku klas bazowych/pochodnych, implementacja zapewnia sprawdzenie w czasie kompilacji deklaracji Wirtualnego destruktora w klasie bazowej. Jeśli zdarzy ci się go pominąć kod nie będzie kompilowany (kliknij " Run (...) "przycisk, aby zobaczyć kompilator komunikat o błędzie).

Drobny problem polega na tym, że zawiera come from boost/move directory, ale kod znajduje się w boost::movelib przestrzeni nazw (subtelna różnica, ale może być irytująca).

Więcej szczegółów można znaleźć w wątku na liście dyskusyjnej boost .

Podziękowania dla Iona Gaztañagi za ten absolutnie unikalny i użyteczny fragment kodu.

 37
Author: Adam Romanek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-05 10:42:08

Możesz wypróbować implementację Howarda Hinnanta ' proof of concept 'unique_ptr<> dla C++03 (disclaimer - I haven ' t):

Jednym z jego przykładów jest zwrócenie unique_ptr<int>:

unique_ptr<int> factory(int i)
{
    return unique_ptr<int>(new int(i));
}
 10
Author: Michael Burr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-10 21:36:16

A może unique_ptr z bibliotekiinterprocess ?

 5
Author: fbrereto,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-01 21:39:09

Użyłem Howarda Hinnanta unique_ptr . Jeśli nie jesteś naprawdę dobry w czytaniu szalonych błędów metaprogramowania z twojego kompilatora, możesz chcieć omijać. Jednak działa podobnie jak unique_ptr w 90% przypadków.

W Przeciwnym Razie sugerowałbym podanie paramterów jako {[0] } i zamianę wewnętrznie na kradzież własności. Aby uzyskać wartości zwracane w stylu unique_ptr, użyj auto_ptr. Przechwyć wartość zwracaną auto_ptr w shared_ptr lub scoped_ptr, Aby uniknąć bezpośredniego użycia auto_ptr.

 4
Author: deft_code,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-02 15:20:37