2013-02-14 8 views
6

Jaki jest najlepszy idiom do przeniesienia unique_ptr<char[]> do unique_ptr<const char[]>?od unique_ptr <char[]> do unique_ptr <const char []>

Przypadek użycia: załóżmy, że tworzysz ciąg C w jakimś buforze. Aby zapewnić poprawne czyszczenie w przypadku wyjątku, ten bufor może być odwołaniem przy użyciu unique_ptr. Po skonstruowaniu łańcucha możesz chcieć przenieść go do jakiegoś elementu klasy, który jest zadeklarowany jako unique_ptr<const char[]>, aby uniknąć dalszej modyfikacji ciągu.

Oto najlepszy mam tak daleko:

std::unique_ptr<const char[]> res; 
std::unique_ptr<char[]> buf(new char[4]); 
buf[0] = 'f'; 
buf[1] = buf[2] = 'o'; 
buf[3] = '\0'; 
res = std::unique_ptr<const char[]>(const_cast<const char*>(buf.release())); 

Wystarczy ruchu nie wydaje się działać, prawdopodobnie ze względu na różne typy Deleter. Nawet pominięcie jawnej obsady od char do const char nie działa, jak omówiono w Should `unique_ptr< T const [] >` accept a `T*` constructor argument?

Czy jest jakiś lepszy idiom do osiągnięcia tego, co opisałem powyżej? Mój kod wygląda dość niezgrabnie i raczej długo zastanawiał się, jak prosty jest pomysł na początku.

+0

użyciu tylko 'res = std :: ruch (buf);' kompiluje dobrze dla mnie w VS2010 i VS2012 i trunk Clang (z trunkem libC++). GCC 4.7.2 na tym dławiki. – Xeo

+1

Wygląda na to, że trunk GCC 4.8 naprawił problem i możesz użyć 'res = std :: move (buf)'. W przeciwnym razie, nie sądzę, żebyś mógł ominąć tę obsadę. Możesz skrócić linię do 'res.reset (const_cast (buf.release()));', chociaż. – Xeo

+0

@Xeo, zarówno informacje o GCC 4.8, jak i krótszy idiom za pomocą 'reset' są bardzo cenne. Opublikuj je jako odpowiedź. – MvG

Odpowiedz

6

Stdlib VS2010 i VS2012 umożliwiają konwersję z res = std::move(buf) jako rozszerzenie oraz jako odpowiedź na DR2118. To samo dotyczy libC++ i GCC 4.8 libstdC++.

Dla GCC 4.7, nie będzie obejść const_cast, ale conajmniej skrócić linię nieco:

res.reset(const_cast<char const*>(buf.release())); 
Powiązane problemy