Hi,
I have a question about using Y_BEHAVIOR_METHOD2 with a class that has inheritance.
First of all, I have to ask if it is possible to use Y_BEHAVIOR_METHOD2 macro with classes with several layers of inheritance and call functions from the parent and any of the children?
If yes then how should the address of the method be provided to the macro?
If no is there any other way to solve the problem?
Thanks a lot in advance for your time and answer.
Using Y_BEHAVIOR_METHOD2 with classes with inheritence
-
- Posts:5
- Joined:13 Jul 2016, 08:38
Re: Using Y_BEHAVIOR_METHOD2 with classes with inheritence
Hi Milad,
sorry, that it took actually ages to answer your questions. But we have been super busy...
and then you can use the casted pointer within the macro.
It's ugly, but it works.
I created a quick and dirty example based on "Hello, yasmine!" for you:
sorry, that it took actually ages to answer your questions. But we have been super busy...
Yes, it is. But it is not very pretty syntactically.First of all, I have to ask if it is possible to use Y_BEHAVIOR_METHOD2 macro with classes with several layers of inheritance and call functions from the parent and any of the children?
The name of the method is not the problem. You can pass it as &base::method or as &derived::method no difference. The problem is the object pointer (the first parameter). You have to cast your pointer outside the macro to the according class.If yes then how should the address of the method be provided to the macro?
Code: Select all
Base* bp = static_cast<Base*>(this);
It's ugly, but it works.
Code: Select all
Layer1* l1 = static_cast<Layer1*>(this);
sxy::simple_state& simple_state_replying = main_region.add_simple_state( "replying", Y_BEHAVIOR_METHOD2( l1, &Layer1::reply ) )
I created a quick and dirty example based on "Hello, yasmine!" for you:
Code: Select all
//////////////////////////////////////////////////////////////////////////////////////////////////////
// //
// This file is part of the Seadex yasmine ecosystem (http://yasmine.seadex.de). //
// Copyright (C) 2016-2018 Seadex GmbH //
// //
// Licensing information is available in the folder "license" which is part of this distribution. //
// The same information is available on the www @ http://yasmine.seadex.de/Licenses.html. //
// //
//////////////////////////////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include "libyasmine/include/yasmine.hpp"
const sxy::event_id HELLO_EVENT = 1;
class Layer1 {
public:
void reply()
{
std::cout << "Hello, yasmine!" << std::endl;
}
};
class Layer2 : public Layer1 {
public:
void wait()
{
std::cout << "waiting" << std::endl;
}
};
class Layer3 : public Layer2 {
public:
Layer3():
error_code_(0),
hello_yasmine_state_machine_()
{
hello_yasmine_state_machine_ = setup_state_machine( "hello yasmine state machine" );
if( check_state_machine_for_defects( *hello_yasmine_state_machine_ ) )
{
hello_yasmine_state_machine_->run();
try
{
hello_yasmine_state_machine_->fire_event( sxy::event_impl::create( HELLO_EVENT ) );
hello_yasmine_state_machine_->fire_event( sxy::event_impl::create( HELLO_EVENT ) );
hello_yasmine_state_machine_->fire_event( sxy::event_impl::create( HELLO_EVENT ) );
hello_yasmine_state_machine_->halt();
}
catch( const std::exception& exception )
{
SX_LOG( hermes::log_level::LL_FATAL, "Unhandled exception: '%'.", exception.what() );
error_code_ = 1;
}
catch( ... )
{
SX_LOG( hermes::log_level::LL_FATAL, "Unknown exception!" );
error_code_ = 2;
}
}
else
{
error_code_ = 3;
}
}
int get_error_code() const
{
return error_code_;
}
private:
typedef sxe::SX_UNIQUE_PTR< sxy::sync_state_machine > state_machine_uptr;
state_machine_uptr setup_state_machine( const std::string& _name )
{
Layer1* l1 = static_cast<Layer1*>(this);
Layer2* l2 = static_cast<Layer2*>(this);
state_machine_uptr state_machine = SX_MAKE_UNIQUE< sxy::sync_state_machine >( _name );
sxy::composite_state& root_state = state_machine->get_root_state();
sxy::region& main_region = root_state.add_region( "main region" );
sxy::initial_pseudostate& initial_pseudostate = main_region.add_initial_pseudostate( "initial" );
sxy::simple_state& simple_state_waiting = main_region.add_simple_state( "waiting", Y_BEHAVIOR_METHOD2( l2, &Layer2::wait ) );
sxy::simple_state& simple_state_replying = main_region.add_simple_state( "replying", Y_BEHAVIOR_METHOD2( l1, &Layer1::reply ) );
state_machine->add_transition( HELLO_EVENT, simple_state_waiting, simple_state_replying );
state_machine->add_transition( sxy::Y_COMPLETION_EVENT_ID, initial_pseudostate, simple_state_waiting );
state_machine->add_transition( sxy::Y_COMPLETION_EVENT_ID, simple_state_replying, simple_state_waiting );
return( state_machine );
}
bool check_state_machine_for_defects( const sxy::sync_state_machine& _state_machine )
{
sxy::state_machine_defects defects;
const bool state_machine_has_no_defects = _state_machine.check( defects );
if( !state_machine_has_no_defects )
{
sxy::write_defects_to_log( defects );
}
return( state_machine_has_no_defects );
}
int error_code_;
state_machine_uptr hello_yasmine_state_machine_;
};
int main()
{
#ifndef SX_NO_LOGGING
hermes::log_manager_template<hermes::std_timestamp_policy>& log_manager = hermes::log_manager::get_instance();
log_manager.set_log_level( hermes::log_level::LL_FATAL );
log_manager.add_logger( SX_MAKE_UNIQUE< hermes::cout_logger >() );
log_manager.run();
sxy::version::log_version();
#endif
Layer3 layer3;
#ifndef SX_NO_LOGGING
log_manager.halt_and_join();
#endif
return( layer3.get_error_code() );
}
-
- Posts:5
- Joined:13 Jul 2016, 08:38
Re: Using Y_BEHAVIOR_METHOD2 with classes with inheritence
The board software removed the line breaks in the code, so here for now without code tags:
//////////////////////////////////////////////////////////////////////////////////////////////////////
// //
// This file is part of the Seadex yasmine ecosystem (http://yasmine.seadex.de). //
// Copyright (C) 2016-2018 Seadex GmbH //
// //
// Licensing information is available in the folder "license" which is part of this distribution. //
// The same information is available on the www @ http://yasmine.seadex.de/Licenses.html. //
// //
//////////////////////////////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include "libyasmine/include/yasmine.hpp"
const sxy::event_id HELLO_EVENT = 1;
class Layer1 {
public:
void reply()
{
std::cout << "Hello, yasmine!" << std::endl;
}
};
class Layer2 : public Layer1 {
public:
void wait()
{
std::cout << "waiting" << std::endl;
}
};
class Layer3 : public Layer2 {
public:
Layer3():
error_code_(0),
hello_yasmine_state_machine_()
{
hello_yasmine_state_machine_ = setup_state_machine( "hello yasmine state machine" );
if( check_state_machine_for_defects( *hello_yasmine_state_machine_ ) )
{
hello_yasmine_state_machine_->run();
try
{
hello_yasmine_state_machine_->fire_event( sxy::event_impl::create( HELLO_EVENT ) );
hello_yasmine_state_machine_->fire_event( sxy::event_impl::create( HELLO_EVENT ) );
hello_yasmine_state_machine_->fire_event( sxy::event_impl::create( HELLO_EVENT ) );
hello_yasmine_state_machine_->halt();
}
catch( const std::exception& exception )
{
SX_LOG( hermes::log_level::LL_FATAL, "Unhandled exception: '%'.", exception.what() );
error_code_ = 1;
}
catch( ... )
{
SX_LOG( hermes::log_level::LL_FATAL, "Unknown exception!" );
error_code_ = 2;
}
}
else
{
error_code_ = 3;
}
}
int get_error_code() const
{
return error_code_;
}
private:
typedef sxe::SX_UNIQUE_PTR< sxy::sync_state_machine > state_machine_uptr;
state_machine_uptr setup_state_machine( const std::string& _name )
{
Layer1* l1 = static_cast<Layer1*>(this);
Layer2* l2 = static_cast<Layer2*>(this);
state_machine_uptr state_machine = SX_MAKE_UNIQUE< sxy::sync_state_machine >( _name );
sxy::composite_state& root_state = state_machine->get_root_state();
sxy::region& main_region = root_state.add_region( "main region" );
sxy::initial_pseudostate& initial_pseudostate = main_region.add_initial_pseudostate( "initial" );
sxy::simple_state& simple_state_waiting = main_region.add_simple_state( "waiting", Y_BEHAVIOR_METHOD2( l2, &Layer2::wait ) );
sxy::simple_state& simple_state_replying = main_region.add_simple_state( "replying", Y_BEHAVIOR_METHOD2( l1, &Layer1::reply ) );
state_machine->add_transition( HELLO_EVENT, simple_state_waiting, simple_state_replying );
state_machine->add_transition( sxy::Y_COMPLETION_EVENT_ID, initial_pseudostate, simple_state_waiting );
state_machine->add_transition( sxy::Y_COMPLETION_EVENT_ID, simple_state_replying, simple_state_waiting );
return( state_machine );
}
bool check_state_machine_for_defects( const sxy::sync_state_machine& _state_machine )
{
sxy::state_machine_defects defects;
const bool state_machine_has_no_defects = _state_machine.check( defects );
if( !state_machine_has_no_defects )
{
sxy::write_defects_to_log( defects );
}
return( state_machine_has_no_defects );
}
int error_code_;
state_machine_uptr hello_yasmine_state_machine_;
};
int main()
{
#ifndef SX_NO_LOGGING
hermes::log_manager_template<hermes::std_timestamp_policy>& log_manager = hermes::log_manager::get_instance();
log_manager.set_log_level( hermes::log_level::LL_FATAL );
log_manager.add_logger( SX_MAKE_UNIQUE< hermes::cout_logger >() );
log_manager.run();
sxy::version::log_version();
#endif
Layer3 layer3;
#ifndef SX_NO_LOGGING
log_manager.halt_and_join();
#endif
return( layer3.get_error_code() );
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
// //
// This file is part of the Seadex yasmine ecosystem (http://yasmine.seadex.de). //
// Copyright (C) 2016-2018 Seadex GmbH //
// //
// Licensing information is available in the folder "license" which is part of this distribution. //
// The same information is available on the www @ http://yasmine.seadex.de/Licenses.html. //
// //
//////////////////////////////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include "libyasmine/include/yasmine.hpp"
const sxy::event_id HELLO_EVENT = 1;
class Layer1 {
public:
void reply()
{
std::cout << "Hello, yasmine!" << std::endl;
}
};
class Layer2 : public Layer1 {
public:
void wait()
{
std::cout << "waiting" << std::endl;
}
};
class Layer3 : public Layer2 {
public:
Layer3():
error_code_(0),
hello_yasmine_state_machine_()
{
hello_yasmine_state_machine_ = setup_state_machine( "hello yasmine state machine" );
if( check_state_machine_for_defects( *hello_yasmine_state_machine_ ) )
{
hello_yasmine_state_machine_->run();
try
{
hello_yasmine_state_machine_->fire_event( sxy::event_impl::create( HELLO_EVENT ) );
hello_yasmine_state_machine_->fire_event( sxy::event_impl::create( HELLO_EVENT ) );
hello_yasmine_state_machine_->fire_event( sxy::event_impl::create( HELLO_EVENT ) );
hello_yasmine_state_machine_->halt();
}
catch( const std::exception& exception )
{
SX_LOG( hermes::log_level::LL_FATAL, "Unhandled exception: '%'.", exception.what() );
error_code_ = 1;
}
catch( ... )
{
SX_LOG( hermes::log_level::LL_FATAL, "Unknown exception!" );
error_code_ = 2;
}
}
else
{
error_code_ = 3;
}
}
int get_error_code() const
{
return error_code_;
}
private:
typedef sxe::SX_UNIQUE_PTR< sxy::sync_state_machine > state_machine_uptr;
state_machine_uptr setup_state_machine( const std::string& _name )
{
Layer1* l1 = static_cast<Layer1*>(this);
Layer2* l2 = static_cast<Layer2*>(this);
state_machine_uptr state_machine = SX_MAKE_UNIQUE< sxy::sync_state_machine >( _name );
sxy::composite_state& root_state = state_machine->get_root_state();
sxy::region& main_region = root_state.add_region( "main region" );
sxy::initial_pseudostate& initial_pseudostate = main_region.add_initial_pseudostate( "initial" );
sxy::simple_state& simple_state_waiting = main_region.add_simple_state( "waiting", Y_BEHAVIOR_METHOD2( l2, &Layer2::wait ) );
sxy::simple_state& simple_state_replying = main_region.add_simple_state( "replying", Y_BEHAVIOR_METHOD2( l1, &Layer1::reply ) );
state_machine->add_transition( HELLO_EVENT, simple_state_waiting, simple_state_replying );
state_machine->add_transition( sxy::Y_COMPLETION_EVENT_ID, initial_pseudostate, simple_state_waiting );
state_machine->add_transition( sxy::Y_COMPLETION_EVENT_ID, simple_state_replying, simple_state_waiting );
return( state_machine );
}
bool check_state_machine_for_defects( const sxy::sync_state_machine& _state_machine )
{
sxy::state_machine_defects defects;
const bool state_machine_has_no_defects = _state_machine.check( defects );
if( !state_machine_has_no_defects )
{
sxy::write_defects_to_log( defects );
}
return( state_machine_has_no_defects );
}
int error_code_;
state_machine_uptr hello_yasmine_state_machine_;
};
int main()
{
#ifndef SX_NO_LOGGING
hermes::log_manager_template<hermes::std_timestamp_policy>& log_manager = hermes::log_manager::get_instance();
log_manager.set_log_level( hermes::log_level::LL_FATAL );
log_manager.add_logger( SX_MAKE_UNIQUE< hermes::cout_logger >() );
log_manager.run();
sxy::version::log_version();
#endif
Layer3 layer3;
#ifndef SX_NO_LOGGING
log_manager.halt_and_join();
#endif
return( layer3.get_error_code() );
}
Re: Using Y_BEHAVIOR_METHOD2 with classes with inheritence
Great, Thank you very much for your answer.
Who is online
Users browsing this forum: No registered users and 1 guest