Reputation: 687
Say I have:
f(T& t){ ... }
which I sometimes want to provide argument for from a function call
T GetT() { ... }
like this:
f(GetT())
Which won't compile even though I'm convinced that the lifetime of T
is guaranteed to last until the end of expression, I also cannot change the T&
to const T&
because I need to modify the object inside f
.
I thought about using T&&
but then when I happen to have lvalue of T
I would need to move()
it, which would make it awkward because I sometimes need to use T
after the call to f
. In my case T
is plain old data so I guess it would work but it doesn't feel right to move an object and use it afterwards.
Is there an elegant way to allow function to take both rval and lval refs to mutable object?
ATM I'm just doing
T t = GetT();
f(t);
Which I feel is at least one useless line and one useless copy of T
.
Upvotes: 0
Views: 342
Reputation: 2124
How about using universal references.
Not sure if you would consider it elegant but it would look something like this:
struct MyStruct
{
int i;
};
template<class T>
void foo(T&& t)
{
static_assert(std::is_base_of<MyStruct,
typename std::remove_reference<T>::type>::value, "ERROR");
t.i = 1024;
}
MyStruct GetMyStruct()
{
return MyStruct();
}
int main()
{
foo(GetMyStruct());
MyStruct ms;
foo(ms);
return 0;
}
Upvotes: 2
Reputation: 687
I came up with a solution to my problem with simple overload:
f(T& t) { ... }
f(T&& t) { f(t); }
But there still has to be a better way.
Upvotes: 0
Reputation: 238311
The way that you're currently doing, i.e. storing the object in a variable, is a proper way to extend the lifetime of the returned object and allow non-const references to bind to it. If GetT
is implemented so that (N)RVO is possible, then no useless copy need to be made because it can be elided.
Upvotes: 1
Reputation: 7368
You cannot bind a reference to a temporany: only const reference can do that.
I suggesto you to look this link C++11 binding rules for const &&
Upvotes: -1