1

I got the following error when I initialize the base class whose constructor takes a reference with a temporary object (jsonrpc::HttpServer(port)). I thought std::move is for this scenario but std::move(jsonrpc::HttpServer(port) doesn't work either. Any idea?

class Server : public jsonrpc::AbstractServer<Server>
{
    public:
        Server(jsonrpc::AbstractServerConnector &conn) : jsonrpc::AbstractServer<Server>(conn)
        {
            //...
        }
};

class MyServer: public Server {
    public: MyServer(int port);
}

// error
MyServer::EnclaveRPC(int port):Server(jsonrpc::HttpServer(port)){}
MyServer::EnclaveRPC(int port):Server(std::move(jsonrpc::HttpServer(port))){}

error: invalid initialization of non-const reference of type ‘jsonrpc::AbstractServerConnector&’ from an rvalue of type ‘jsonrpc::AbstractServerConnector’ : Server(jsonrpc::HttpServer(port)){

qweruiop
  • 3,156
  • 6
  • 31
  • 55
  • Copy&paste the complete error message. –  Sep 12 '17 at 17:20
  • 1
    Possible duplicate of [How come a non-const reference cannot bind to a temporary object?](https://stackoverflow.com/questions/1565600/how-come-a-non-const-reference-cannot-bind-to-a-temporary-object) – Kevin Sep 12 '17 at 17:20

3 Answers3

4
MyServer::EnclaveRPC(int port):Server(jsonrpc::HttpServer(port)){}

here you create a temporary object of type jsonrpc::HttpServer (rvalue) and try to pass it as an lvalue reference, which is prohibited for a good reason. jsonrpc::AbstractServer can store it as a member (most probably it does) to use it later, but the temp object will be deleted before executing the next line of you program

P.S.

jsonrpc library provides a weak interface of jsonrpc::AbstractServer. It should take ownership of a connection (e.g. by std::unique_ptr) or at least shared ownership by std::shared_ptr

Andriy Tylychko
  • 15,967
  • 6
  • 64
  • 112
2

Your class is not the owner of the jsonrpc::AbstractServerConnector, since a reference does not carry ownership.

In that matter, you must have it sent to you, since the owner is external:

struct Server : jsonrpc::AbstractServer<Server>
{
        Server(jsonrpc::AbstractServerConnector& conn) : jsonrpc::AbstractServer<Server>(conn)
        {
            //...
        }
};

struct MyServer : Server {
    MyServer(jsonrpc::AbstractServerConnector& conn) : Server{conn} {}
};

This is probably what you need.


However, If you insist at being the owner of the resource, you can create a owning class that would be your first parent:

struct HttpConnectionOwner {
    explicit HttpConnectionOwner(int port) : conn{port} {}

    jsonrpc::HttpServer conn;
};

struct MyServer : HttpConnectionOwner, Server {
    explicit MyServer(int port) : HttpConnectionOwner{port}, Server{conn} {}
};

Also, if you have many connection type, you can make your class choose which type of connection you need:

template<typename ConnectionType>
struct MyServer : ConnectionType, Server {
    using ConnectionType::conn; // conn is now a dependent name

    explicit MyServer(int port) : ConnectionType{port}, Server{conn} {}
};

using MyHttpServer = MyServer<HttpConnectionOwner>;
using MyWebSocketServer = MyServer<WebSocketConnectionOwner>;
Guillaume Racicot
  • 39,621
  • 9
  • 77
  • 141
0

You could always just take a pointer, but to be 100% safe, make it a unique_ptr or shared_ptr like this:

class testTempUnique {
public:
  testTempUnique(unique_ptr<int> &inPtr)
    : myPtr{ std::move(inPtr) } { }

  unique_ptr<int> myPtr;
};
auto mygeneratedClass = testTempUnique(make_unique<int>(5));
cout << "value inside is: " << *(mygeneratedClass.myPtr) << endl;

I have an int there but you get the idea. And if you want to make it so the object can be "valid" other places, use a shared_ptr<T> instead.

Kevin Anderson
  • 6,850
  • 4
  • 32
  • 54