error: cannot bind '' lvalue to ''

Hi all!

I read in "The C++ Programming Lanuage, fourth edition" that if all a function does is pass a parameter to a function I should use move semantics.

Here in my project I'm trying to do that but I am getting errors.

My code (with all the irrelevant bits removed):

Radio.cpp:

void RadioContainer::handle_ack_message(byte&& msg)
{
  switch (msg)
  {
  ...
  }
}

...
void RadioContainer::radio_transmit_message(byte msg)
{
  ...
  handle_ack_message(msg);
  ...
}
...

Radio.h:

class RadioContainer 
{
  public:
    void handle_ack_message(byte&& msg);
    ...
};

errors:

/tmp/181747193/build/sketch/Radio.cpp: In member function 'void RadioContainer::radio_transmit_message(byte)':

/tmp/181747193/build/sketch/Radio.cpp:76:27: error: cannot bind 'byte {aka unsigned char}' lvalue to 'byte&& {aka unsigned char&&}'

handle_ack_message(msg);

^

In file included from /tmp/181747193/build/sketch/Radio.cpp:3:0:

/tmp/181747193/build/sketch/Radio.h:60:10: note: initializing argument 1 of 'void RadioContainer::handle_ack_message(byte&&)'

void handle_ack_message(byte&& msg);

^

exit status 1

the function requires a reference to a reference, but you're trying to pass it a byte.

(You missed out some of the relevant bits too)

TheMemberFormerlyKnownAsAWOL:
the function requires a reference to a reference, but you're trying to pass it a byte.

That's not a reference to a reference (such a thing doesn't exist), it's an rvalue reference.

ningaman151:
that if all a function does is pass a parameter to a function I should use move semantics.

That only makes sense if copying is expensive (or impossible). A byte is best passed by value.

Pieter

My grasp of this is tenuous at best, but I'll take a shot. Inside your function 'void RadioContainer::radio_transmit_message()', msg is a local variable -- therefore, it's a 'lvalue'. So, when you call 'handle_ack_message()' from this function, you're trying to pass an 'lvalue' to a function that only accepts an 'rvalue'.

That's my best guess anyway.

PieterP:
That's not a reference to a reference (such a thing doesn't exist), it's an rvalue reference.

Brain fart.

The parenthetic comment rests though.

gfvalvo:
My grasp of this is tenuous at best, but I'll take a shot. Inside your function 'void RadioContainer::radio_transmit_message()', msg is a local variable -- therefore, it's a 'lvalue'. So, when you call 'handle_ack_message()' from this function, you're trying to pass an 'lvalue' to a function that only accepts an 'rvalue'.

That's my best guess anyway.

That's not it. You can pass lvalues to functions taking rvalues as arguments (tested using a C++ editor).

PieterP:
That only makes sense if copying is expensive (or impossible). A byte is best passed by value.

Pieter

How would you go about doing it for expensive operations?

ningaman151:
How would you go about doing it for expensive operations?

If you're only going to use the object in the functions you're calling, pass it by const reference.

If you're going to use it to construct the object you're going to return, or if you are going to give it away to somewhere else, use std::move (or std::forward if you're using templates and universal references).

PieterP:
If you're only going to use the object in the functions you're calling, pass it by const reference.

If you're going to use it to construct the object you're going to return, or if you are going to give it away to somewhere else, use std::move (or std::forward if you're using templates and universal references).

I thought the standard library is unavailable for Arduino (AVR in general)

ningaman151:
I thought the standard library is unavailable for Arduino (AVR in general)

Correct.

But this is not an issue, I maintain a library that supports parts of the STL. Things like std::move are nothing special, and there's no reason not to use them on a microcontroller. (Well, using std::move kind of implies dynamic memory usage, but still, std::move itself is just a cast to an rvalue reference.)

Just #include <AH/STL/utility> to use std::move and std::forward etc.
If the STL is supported on the platform you're using (i.e. everything but AVR), it uses the toolchain's version, otherwise, it uses the fallback version provided by the library.