0

Original C-style code

Environment* env = Environment::createEnvironment(Environment::Mode::DEFAULT);
Connection* conn = env->createConnection(db_user_name, db_password, db_conn_str);
...
env->terminateConnection(conn);
Environment::terminateEnvironment(env);

I try get C++ with RAII code like this

std::unique_ptr<Environment, decltype(&Environment::terminateEnvironment)>env (Environment::createEnvironment(Environment::Mode::DEFAULT), &Environment::terminateEnvironment);
std::unique_ptr<Connection, decltype(&Environment::terminateConnection))>con(env->createConnection(db_user_name, db_password, db_conn_str), &(env->terminateConnection));

It's work in first line, but I get error with second line. I newbie in smart pointers. How I can get unique_ptr for Connection pointer???

  • So.. the original C-style has a bunch of pointers-to-functions in the `Environment` structure? Because that the only way that code will possibly compile in C. – WhozCraig Feb 06 '20 at 10:16
  • I personally prefer to create dedicated `Deleter` instead of function pointer. – Jarod42 Feb 06 '20 at 10:27

1 Answers1

0

You cannot use a non-static member function as deleter. Instead write a lambda capturing the required env pointer and pass that to the std::unique_ptr:

auto connectionDeleter = [env=env.get()](auto ptr){
    env->terminateConnection(ptr);
};
std::unique_ptr<Connection, decltype(connectionDeleter)> con(env->createConnection(db_user_name, db_password, db_conn_str), connectionDeleter);

Note that this will not prevent you from accidentally freeing env before open connections are closed. If you want to have that guarantee, you need to pass env on as shared_ptr to the deleter:

std::shared_ptr<Environment> env(Environment::createEnvironment(Environment::Mode::DEFAULT), &Environment::terminateEnvironment);

auto connectionDeleter = [env](auto ptr){
    env->terminateConnection(ptr);
};

std::unique_ptr<Connection, decltype(connectionDeleter)> con(env->createConnection(db_user_name, db_password, db_conn_str), connectionDeleter);
walnut
  • 21,629
  • 4
  • 23
  • 59
  • This example return error "term does not evaluate to a function taking 1 arguments". For first and second. – Naydachi Kamikadze Feb 06 '20 at 10:43
  • @NaydachiKamikadze Which line? – walnut Feb 06 '20 at 10:47
  • Error C2064 term does not evaluate to a function taking 1 arguments MSVC\14.24.28314\include\memory 1873 – Naydachi Kamikadze Feb 06 '20 at 10:51
  • @NaydachiKamikadze Which line in the code in the answer does the error refer to? I cannot really test it myself, because you didn't provide a [repro] to test against. – walnut Feb 06 '20 at 10:52
  • line 1873 It's not my code, it's not build project with compiler error from Memory file. It's destructor for ~unique_ptr() – Naydachi Kamikadze Feb 06 '20 at 10:54
  • ~unique_ptr() noexcept { if (_Mypair._Myval2) { _Mypair._Get_first()(_Mypair._Myval2); } } _Mypair._Get_first() and continue – Naydachi Kamikadze Feb 06 '20 at 10:56
  • @NaydachiKamikadze Which of the unique_ptr's? My first example, the second, or the one in your question? There is information in the output tab showing where the problem originates in the user code. – walnut Feb 06 '20 at 10:56
  • Thanks it's my mistake, I try run this – Naydachi Kamikadze Feb 06 '20 at 10:58
  • Thanks a lot, it's work. But I think that I not used more one connection :)) – Naydachi Kamikadze Feb 06 '20 at 11:11
  • How I can declare my unique_ptr??? std::unique_ptr> ptr = std::unique_ptr(env->createConnection(db_user_name, db_password, db_conn_str), connectionDeleter); Not work – Naydachi Kamikadze Feb 06 '20 at 11:39
  • @NaydachiKamikadze The type is `std::unique_ptr`, not `std::unique_ptr>`. You do not need to repeat the type twice. `auto ptr = std::unique_ptr(env->createConnection(...), connectionDeleter);` or the form in my answer are both fine. If you want to specify the type somewhere else, then you should write a full functor object that can be named everywhere instead of using a lambda, see https://stackoverflow.com/questions/356950/what-are-c-functors-and-their-uses – walnut Feb 06 '20 at 12:28
  • Or you can make the type `std::unique_ptr`. – walnut Feb 06 '20 at 12:29