user1476176
user1476176

Reputation: 1095

Passing a temporary to a function as an lvalue

I am trying to implement a list class as follows

class NOlist { // "Non-Owning" list

protected:

    int nData;
    double* data;

    // Construct given an existing data array
    NOlist(int nDataArg, double* dataArg) : nData(nDataArg), data(dataArg) {}

public:

    // Copy constructor
    NOlist(const NOlist&)=default;

    // Return NOlist representing sub-list 
    NOlist subList(const int at) {
        return NOlist(nData-at, data+at);
    }

    // Operators
    NOlist& operator*=(const double& factor) {
        for(int i = 0; i < nData; i++) {
            data[i] *= factor;
        }
        return *this;
    }

};

struct List : public NOlist { // Wrapper (responsible for memory management only)

    List(const int nDataArg) : NOlist(nDataArg, new double[nDataArg]) {}

    ~List() { delete[] data; }

};

void triple(NOlist& arg) {
     arg *= 3.0;
}

I like this pattern because it makes it possible to things like A.subList(1).subList(2), which makes it convenient to implement some things recursively. My actual case is more complicated, but I've stripped it down to something which represents the core idea.

This creates a problem in the following

List A(50);

// [code to set A...]

A.subList(5) *= 3; // works 
triple(A.subList(5)); // error: invalid initialization of non-const reference of type 'NOlist&' from an rvalue of type 'NOlist' 

My guess is that, in the second-last line, A.subList(5) is this during the call to operator*= and is therefore guaranteed to last for the entire call, but in the second case it is just an argument and therefore its lifetime gets no extension. I can get around the error by replacing the last line with

NOlist Atmp(A.subList(5)); // make the subList non-temporary
triple(Atmp);              // modify the subList

...but I'm wondering whether there is a more elegant solution. Essentially I would like to prolong the life of a temporary for the duration of a function call and allow it to be used as an lvalue during that lifespan.

Upvotes: 0

Views: 97

Answers (1)

Anteru
Anteru

Reputation: 19374

I presume your function triple takes a reference. If you make it take the parameter by-value, it will just work (equivalent to the code you wrote as a workaround) but it won't require you to manually create the temporary object (instead, it will be created at function-call time.)

Assuming your NOlist is cheap to create/copy, that's a valid solution. Alternatively, you could have a special proxy type just for that use case.

Upvotes: 0

Related Questions