forward a struct with a unique_ptr

I'm attempting to pass a rvalue struct, which has a unique_ptr as one of its members, as an argument to a member function, which then uses the rvalue in a std::pair definition.

Compile error however occurs, which is:
 
error: no matching function for call to ‘std::pair<int, db_info>::pair(int&, db_info)’


the header looks as follows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <include/SQLAPI.h>
#include <map>
#include <memory>

struct db_info {
  std::string product;
  std::string con_str;
  std::string usr;
  std::string pswd;
  std::string modify_begin; 
  std::string select_begin;
  SAClient_t con_cl; // type of connection
  std::unique_ptr<SAConnection> con;
};

class db_connector {
  using info_map = std::map<int, db_info>;

  public:
    db_connector() { }
    ~db_connector() { }
    using const_iterator = info_map::const_iterator;

    const_iterator begin() const { return db_cons.begin(); }
    const_iterator end() const { return db_cons.end(); }

    void add_connection(int, db_info &&);
    db_info * get_db_info(int db_id) { return &db_cons.at(db_id); }
    bool connect (int);
    bool disconnect (int);

  private:
    info_map db_cons;
};


the .cpp file looks like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include "db_connector.h"

//void db_connector::add_connection(int db_id, db_info dbi) {
void db_connector::add_connection(int db_id, db_info && dbi) {
  db_cons.insert(std::make_pair(db_id, std::forward<db_info>(dbi) ));  
  // db_cons.insert(std::make_pair(db_id, dbi)); // this doesn't compile, because db_info has a unique_ptr as an attribute, which cannot be copied.
}

bool db_connector::connect (int db_id) {
  db_info dbi {db_cons.at(db_id)};
  try {
    db_cons.at(db_id).con->Connect(dbi.con_str.c_str(), dbi.usr.c_str(), dbi.pswd.c_str(), dbi.con_cl);
  }
  catch(SAException &x) {
    // thread safe log message required
    // std::cout << (const char*)x.ErrText() << "\n";
    return false;
  }
  return true;
}

bool db_connector::disconnect (int db_id) {
  try {
    db_cons.at(db_id).con->Disconnect();
  }
  catch(SAException &x) {
    // thread safe log message required
    // std::cout << (const char*)x.ErrText() << "\n";
    return false;
  }
  return true;
}


The error occurs on this line "db_cons.insert(std::make_pair(db_id, std::forward<db_info>(dbi) ));"
I used a std::forward on an rvalue, since I thought that would get around the fact that a unique_ptr is part of the struct.

Can somebody explain why the error occurs and how to get around the error?
Use std::forward only with forwarding references
(to propagate the value category that an object had when the call was made).

To specify that an object may be moved from, use std::move

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>
#include <string>
#include <memory>
#include <map>

struct SAConnection { /* ... */ };

enum SAClient_t : int ;

struct db_info {

  std::string product;
  std::string con_str;
  std::string usr;
  std::string pswd;
  std::string modify_begin;
  std::string select_begin;
  SAClient_t con_cl; // type of connection
  std::unique_ptr<SAConnection> con;
};

using info_map = std::map<int, db_info>;
info_map db_cons ;

void add_connection( int db_id, db_info&& dbi ) { 
// or better: void add_connection( int db_id, db_info dbi ) { // pass by value

    db_cons.emplace( db_id, std::move(dbi) ) ;

    // note: this clumsier construct would also work
    // db_cons.insert( std::make_pair( db_id, std::move(dbi) ) ) ;
}

int main() {
    
     db_info dbi ;
     dbi.con = std::make_unique<SAConnection>() ;
     // ...

     add_connection( 72, std::move(dbi) ) ;
}

http://coliru.stacked-crooked.com/a/2a302124f0e62934
Topic archived. No new replies allowed.