How can I accept both rvalue and lvalue non-const parameter type

83 Views Asked by At

I'm repeatedly running into the problem of accepting a non-const reference parameter, since it seems taking an rvalue parameter prevents accepting lvalues and vice versa. Here's an example

void read(File &file)// I want to modify file
{
    SomeClass someObject;
    file.readInto(&someObject);//readInto is a non-const method
    // do something with the data populated in someObject
}

But when I try to call read I have a problem if I try two different calling conventions

//this works just fine
File f1 = File::open("some_file_path");
read(f1);

// However this fails
read( File::open("some_file_path") );//because open returns an rvalue

The problem I have is if I change the parameter to a non-const rvalue than I can't pass the lvalue anymore. Am I doomed to always provide an override (or template) that takes the rvalue reference type and simply calls out to the lvalue override?

1

There are 1 best solutions below

1
On

Since you updated the question, I suggest doing this:

void read(File& file)
{
    SomeClass someObject;
    file.radInto(&someObject);
    // ...
}

void read(File&& file) { read(file); }

That will handle both lvalues and rvalues with minimal code repetition.


I think your read function should simply take a File&:

void read(File& file) // I want to modify file
{
    SomeClass someObject;
    file.readInto(&someObject);//Modifies file
    // do something with the data populated in someObject
}

Then you can call:

// OK
std::shared_ptr<File> f1 = File::open("some_file_path");
read(*f1);

// OK
read( *File::open("some_file_path") );

Added benefit: the function is not limited to shared_ptr, and works with any File independently of how its memory is managed.


Alternatively, use a forwarding reference:

template <typename T>
void read(T&& file)// I want to modify file
{
    SomeClass someObject;
    file->readInto(&someObject);//Modifies file
    // do something with the data populated in someObject
}