In function 'int main()':
15:24: error: invalid initialization of non-const reference of type 'Event&' from an rvalue of type 'Event'
3:6: note: in passing argument 1 of 'void HandleEvent(Event&)'
You can't pass an r-value (temp) as a parameter expecting a ref. This either has to be const ref or passed by value. In HandleEvent(Event()), the return value from Event() is an r-value so can't be passed as an arg requiring a ref. When e is of type Event and passed as a param then this is an l-value and can be passed to a ref param.
That function wants to modify variable of the caller. How would the function call benefit the caller, if the caller could pass unnamed temporary int to the function? The caller could not use the answer that function gives.
Or, what if I call test(7);? One can't modify literal constant either.
While void test(Event&); is about passing data from function to caller, the void test(const Event&); is about passing a value to function without creating a copy (and to some extent, so is void test(Event&&);).
Thanks. I do understand the concept, I just need a better understanding when (not) to use it.
I'm still running into some problems though. Hopefully you can help me.
I'm trying to create an event-handling-system (which you might already guessed)
enum EventType { KeyPressed, KeyReleased };
class Event
{
public:
Event(EventType type) : Type(type)
{ }
EventType Type;
};
class KeyEvent : public Event
{
public:
KeyEvent(EventType type, int key) : Event(type), Key(key)
{ }
int Key;
};
class KeyPressedEvent : public KeyEvent
{
public:
KeyPressedEvent(int key) : KeyEvent(KeyPressed, key)
{ }
};
I create and pass the event:
HandleEvent(KeyPressedEvent(key)); // key is received from GLFW
I have an event-handler like this:
1 2 3 4 5 6 7 8 9 10 11
void HandleEvent(Event e) // or (const Event& e) as considered in my first question
{
switch (e.Type)
{
case KeyPressed:
// here I would like to cast e to a KeyPressedEvent, but I don't know how
// I tried KeyPressedEvent ke = (KeyPressedEvent)e;
// and KeyPressedEvent ke = static_cast<KeyPressedEvent>(e);
break;
}
}
It does work when I use pointers and pass new KeyPressedEvent(key) to the event-handler, but doesn't that create too much overhead? Especially when I implement a mousemoved-event which would create a new event on the heap every frame during the move?
> Is it possible to create a variable and simultaneously pass it as reference to another function?
We need to extend the lifetime of the anonymous temporary object.
One way is to make the parameter an lvalue reference to const, as explained above.
If the object is to be modified by the function, hand over the ownership of the temporary object to the function:
make the parameter an rvalue reference. For example:
#include <iostream>
#include <vector>
struct event { int event_id = 999 ; std::string description = {} ; bool handled = false ; } ;
std::vector<event> handled_events ;
void handle( event&& ev ) // handle assumes ownership of the event passed to it
{
ev.handled = true ;
handled_events.push_back( std::move(ev) ) ; // and transfers the ownership to the vector
}
int main()
{
handle( { 22, "test event" } ) ; // rvalue
handle( {} ) ; // rvalue
event ev { 33, "another event" } ; // lvalue
handle( std::move(ev) ) ; // result of std::move is an rvalue
// don't use ev anymore; it is moved from. (it may be in an unspecified state)
}