Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

from unique_ptr<char[]> to unique_ptr<const char[]>

What's the best idiom to move a unique_ptr<char[]> to a unique_ptr<const char[]>?

Use case: suppose you create a C string in some buffer. To ensure proper cleanup in case of an exception, that buffer could be references using a unique_ptr. Once the string is constructed, you might want to move it to some class member, which is declared unique_ptr<const char[]> to avoid further modification of the string.

Here is the best I have so far:

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()));

Simply moving doesn't seem to work, probably due to the different deleter types. Even omitting the explicit cast from char to const char does not work, as discussed in Should `unique_ptr< T const [] >` accept a `T*` constructor argument?

Is there any better idiom to achieve what I outlined above? My code looks pretty clumsy and rather lengthy considered how simple the concept sounds at first.

like image 850
MvG Avatar asked Feb 14 '13 11:02

MvG


2 Answers

VS2010 and VS2012's stdlib allow conversion with res = std::move(buf) as an extension and as a response to DR2118. Same goes for libc++ and GCC 4.8's libstdc++.

For GCC 4.7, you won't get around the const_cast, but atleast you can shorten the line somewhat:

res.reset(const_cast<char const*>(buf.release()));
like image 187
Xeo Avatar answered Sep 23 '22 16:09

Xeo


The Smart Ptr library of Boost has generic pointer cast functions that work with the smart pointers from that library as well as those from STL. In particular, const_pointer_cast can do what you need:

#include <boost/pointer_cast.hpp>

// ...
res = boost::const_pointer_cast<const char[]>(std::move(buf));
like image 38
ingomueller.net Avatar answered Sep 25 '22 16:09

ingomueller.net