I'm using RocksDB which requires a pointer to a pointer to open:
rocksdb::DB* db{nullptr};
const rocksdb::Status status = rocksdb::DB::Open(options, path, &db);
As expected, I'd like to use a unique_ptr
. However, unfortunately if I do this:
std::unique_ptr<rocksdb::DB> db;
const rocksdb::Status status = rocksdb::DB::Open(options, fileFullPath, &(db.get()));
I get:
error: lvalue required as unary ‘&’ operand
and if I use a raw pointer and then create a unique_ptr
:
std::unique_ptr<rocksdb::DB> _db; // Class member
rocksdb::DB* db;
const rocksdb::Status status = rocksdb::DB::Open(options, fileFullPath, &db));
_db = std::make_unique<rocksdb::DB>(db);
I get:
error: invalid new-expression of abstract class type ‘rocksdb::DB’
{ return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }
How can I use unique_ptr
with this?
CodePudding user response:
Using a raw pointer to accept the value from Open()
is the correct solution, since that is what the function is expecting.
However, the way you are creating the unique_ptr
afterwards is not correct.
Use this instead:
std::unique_ptr<rocksdb::DB> _db; // Class member
...
rocksdb::DB* db;
const rocksdb::Status status = rocksdb::DB::Open(options, fileFullPath, &db);
_db = std::unique_ptr<rocksdb::DB>(db);
Alternatively:
std::unique_ptr<rocksdb::DB> _db; // Class member
...
rocksdb::DB* db;
const rocksdb::Status status = rocksdb::DB::Open(options, fileFullPath, &db);
_db.reset(db);
std::make_unique()
creates a new object of the specified type, and then wraps the raw pointer inside of a new std::unique_ptr
.
On the other hand, unique_ptr::operator=
and unique_ptr::reset()
merely update an existing std::unique_ptr
with a new raw pointer (destroying the object pointed by the old raw pointer that is being replaced).
Since rocksdb::DB
is an abstract type, you can't directly create instances of it, which is why your std::make_unique()
calls fails to compile. But even if you could create DB
objects directly, std::make_unique<rocksdb::DB>(db)
would be passing db
as a parameter to the rocksdb::DB
constructor, which is not what you want in this situation anyway. You just want the _db
smart pointer to take ownership of the db
raw pointer.