Search code examples
c++gccpass-by-referencetemporary-objectslvalue-to-rvalue

How do I pass a temporary object as a non-const reference into a member function?


We are creating a class designed to send information out from the current module (the specifics are not relevant to this question). An object of this type is created and populated with a portion of the data that needs to be sent, and then passed into a (different class) member function. That function provides the object with the rest of the data, and then triggers the send, via a call in the object itself. Because the information being passed in is dynamic, the intention is that the information transfer object be a temporary one, created with the latest data. The design we lined out is in the distilled source code below, but gcc/C++ does not allow this, giving the error shown.

The question is, how can we accomplish the intended behavior, using temporary objects (nice for avoiding memory leaks) that can be modified and used by the called function?

gcc compiler error:

infoxfer.cpp: In function ‘int main()’:
infoxfer.cpp:54:43: error: cannot bind non-const lvalue reference of type ‘XferInfo&’ to an rvalue of type ‘XferInfo’
   51 |     callee.doSomething("Something param", XferInfo("from main()"));
      |                                           ^~~~~~~~~~~~~~~~~~~~~~~
infoxfer.cpp:36:62: note:   initializing argument 2 of ‘void Callee::doSomething(const string&, XferInfo&)’
   33 |     void doSomething(const string& somethingParam, XferInfo& xferInfo)
      |                                                    ~~~~~~~~~~^~~~~~~~

The distilled sample code:
infoxfer.cpp:

#include <iostream>
using std::cout;
using std::endl;

#include <string>
using std::string;

class XferInfo
{
private:
    const string mCallerInfo;
    string mCalleeInfo;

public:
    XferInfo(const string& callerInfo) : mCallerInfo(callerInfo)
    {}

    void setCalleeInfo(const string& calleeInfo)
    {
        mCalleeInfo = calleeInfo;
    }

    void sendData()
    {
        // simulate sending data
        cout << mCallerInfo << " | " << mCalleeInfo << endl;
    }
};

class Callee
{
public:
    void doSomething(const string& somethingParam, XferInfo& xferInfo)
    {
        // complete data for xfer
        xferInfo.setCalleeInfo(somethingParam);

        // simulate doing something
        cout << "do something" << endl;

        // send the complete info
        xferInfo.sendData();
    }
};

int main()
{
    cout << "start" << endl;

    Callee callee;
    callee.doSomething("Something param", XferInfo("from main()"));

    cout << "end" << endl;

    return 0;
}

Solution

  • As mentioned in the comments, you could simply change your doSomething function to accept an rvalue reference to the passed XferInfo object (using the double &&):

        void doSomething(const string& somethingParam, XferInfo&& xferInfo)
        {
            // complete data for xfer
            xferInfo.setCalleeInfo(somethingParam);
            // ... and so forth ...
    

    From the linked cppreference page:

    Rvalue references can be used to extend the lifetimes of temporary objects (note, lvalue references to const can extend the lifetimes of temporary objects too, but they are not modifiable through them)