Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting the pointer to an object pointed towards by a smart pointer - Ivalue error

Tags:

c++

I am currently trying to call a sqlite3 library function, and it expects me to pass it a sqlite3**.

Here is my current code. I have one working part, and one part that gives me an error:

sqlite3 *sqlite = m_db.get();
if (sqlite3_open(std::string(m_dbName.begin(), m_dbName.end()).c_str(), &sqlite))
{

}

if (sqlite3_open(std::string(m_dbName.begin(), m_dbName.end()).c_str(), &(m_db.get()) ))
{

}

My m_db field looks like this:

std::unique_ptr<sqlite3> m_db = nullptr;

Of the two examples I displayed, the first one is working perfectly fine. However, the second gives me this error. Note that this is coming from the &(m_db.get()) part:

“Address expression must be an lvalue or a function designator”

I read up a little bit about lvalues and rvalues, but I can't seem to figure out why this syntax would not be possible. As far as I understood by now, the problem is that the return value of the .get() operation is merely only a temporary expression result, and therefore doesn't have an identifiable location in memory where I could fetch the adress from.

There has to be a way to achieve this in one statement, I guess.

Can anyone explain to me why this is not working and how I can possibly fix it?

like image 840
Sossenbinder Avatar asked May 27 '16 08:05

Sossenbinder


2 Answers

The & operator can only be used with an lvalue (or with a qualified id when making pointers-to-member). The expression m_db.get() is an rvalue because it returns a pointer by value, not by reference, so you cannot take its address.

unique_ptr provides no method for accessing the underlying pointer as a reference, you'll need to store a copy somewhere as in your first example.

like image 154
user657267 Avatar answered Oct 15 '22 11:10

user657267


A smart pointer stores a pointer and returns it on get. What you want to do here is the opposite: you get a pointer from sqlite3_open and want to store it in a smart pointer. So you would do something like

sqlite3* db = nullptr;
sqlite3_open(..., &db);
m_db.reset(db);

As the main feature of the unique_ptr is to delete the contained pointer in its destructor, I'm not sure if it makes sense to use it here. As far as I understand it, you are supposed to call sqlite3_close on the returned pointer, not delete it.

like image 28
Karsten Koop Avatar answered Oct 15 '22 11:10

Karsten Koop