Is it possible to bind functions with derived parameters ? And if how ? I would like to be able to store function points to various functions that all have a similar signature, namely they take a class with input data and return a class with output values. But the different functions require and provide different parameters, hence I am trying to register functions that take derived message classes.
The following code works in part. I can register the function MathService::blank and I can later call it. But I cannot add MathService::add.
The error I get is:
main.cpp:70:93: error: conversion from ‘std::_Bind_helper&)(RequestMessage&, ReplyMessage&), MathService&, const std::_Placeholder<1>&, const std::_Placeholder<2>&>::type {aka std::_Bind(MathService*, std::_Placeholder<1>, std::_Placeholder<2>)>}’ to non-scalar type ‘Service::serviceFunction_t {aka std::function}’ requested
serviceFunction_t fn = bind( methodPtr, objectPtr, placeholders::_1, placeholders::_2 );
#include <functional>
#include <unordered_map>
#include <iostream>
using namespace std;
// base class for messages passed around
class BaseMessage
{
public:
virtual void print()
{
cout << "BaseMessage\n";
}
};
// request message with data passed to the service
class RequestMessage : public BaseMessage
{
public:
RequestMessage( int a_, int b_ ) : a( a_ ), b( b_ ) {}
int a;
int b;
void print()
{
cout << "RequestMessage a=" << a << " b=" << b << endl;
}
};
// reply message with return values from the service
class ReplyMessage : public BaseMessage
{
public:
ReplyMessage() : sum( 0 ) {}
int sum;
void print()
{
cout << "ReplyMessage sum=" << sum << endl;
}
};
// Example service provider
class MathService
{
public:
void blank( BaseMessage& request, BaseMessage& reply )
{
request.print();
reply.print();
}
void add( RequestMessage& request, ReplyMessage& reply )
{
reply.sum = request.a + request.b;
}
};
// Class manages services, register a new service with addService and call the service by name using call
class Service
{
public:
using serviceFunction_t = function<void ( BaseMessage&, BaseMessage& )>;
template<class Method, class Obj>
void addService( string name, Method methodPtr, Obj objectPtr )
{
serviceFunction_t fn = bind( methodPtr, objectPtr, placeholders::_1, placeholders::_2 );
pair< string, serviceFunction_t> entry( name, fn );
mFunctionMap.insert( entry );
}
void call( const string& name, BaseMessage& request, BaseMessage& reply )
{
std::unordered_map<string, serviceFunction_t>::const_iterator it;
it = mFunctionMap.find( name );
if( it == mFunctionMap.end() ) {
std::cout << "service not found: " << name << endl;
return;
}
serviceFunction_t fn = it->second;
fn( request, reply );
}
private:
unordered_map<string, serviceFunction_t> mFunctionMap;
};
int main()
{
MathService math;
Service service;
// can add a service with BaseMessages
service.addService( "blank", &MathService::blank, &math );
//*****************************************************
// PROBLEM is here !!
// can not add a service with derived message types, this causes the bind call to fail in Service::addService()
service.addService( "add", &MathService::add, &math );
//*****************************************************
// this works
BaseMessage req1, rep1;
service.call( "blank", req1, rep1 );
// so does this
RequestMessage req2( 1, 2 );
ReplyMessage rep2;
service.call( "blank", req2, rep2 );
// this service is not registered
service.call( "add", req2, rep2 );
}
1) do is a reserved C++ keyword, so your code as-this will never compile
2) std::placeholders_1 does not exist, you surely meant std::placeholders::_1
3) Once this is fixed, yes, it compiles.
Related
I have recently returned to Visual C++ after a while programming in C where callbacks are much easier.
I have a singleton class which controls 0..* connected devices.
My idea is to create a function in this class which will iterate over the set of
connected devices and publish it via a callback to whatever might require it.
e.g.
Singleton class
typedef void (CALLBACK * PortListCallback_t)(ptrConstCComPortInfo_t);
.
.
.
void CCommsMgr::listPorts(PortListCallback_t cb)
{
PortInfoSetConstIter_t i;
for (i = m_setPorts.begin(); i != m_setPorts.end(); i++)
{
cb(*i);
}
}
In the first instance the consumer is an MFC dialog class which works fine if it's callback is static. However in order to access member data/functions of the dialog class I would need to pass 'this' to the singleton class and have it reflected back.
e.g.
Singleton class
typedef void (CALLBACK * PortListCallback_t)(void *, ptrConstCComPortInfo_t);
.
.
.
void CCommsMgr::listPorts(void *pObj, PortListCallback_t cb)
{
PortInfoSetConstIter_t i;
for (i = m_setPorts.begin(); i != m_setPorts.end(); i++)
{
cb(pObj, *i);
}
}
Dialog Class
static void CALLBACK getPorts(void *obj, ptrConstCComPortInfo_t port);
.
.
.
void CALLBACK CMFC_iTFTPDlg::getPorts(void *obj, ptrConstCComPortInfo_t port)
{
CMFC_iTFTPDlg *pThis = (CMFC_iTFTPDlg*)obj;
// do something with it
}
My question - Is there a better way of doing this? Static functions feel like a kludge and I do not want the Singleton class to be constrained by how it might be used.
If I remove the static on getPorts it will not compile. To repeat myself the Singleton class should have no knowledge of it's consumer.
With help from the excellent hints from WhozCraig, this is what I came up with:
#include <functional> // std::function, std::bind, std::placeholders
#include <iostream>
#include <vector>
class ConstCComPortInfo {};
using ptrConstCComPortInfo_t = ConstCComPortInfo*;
using callback_t = void(void*, ptrConstCComPortInfo_t);
using function_t = std::function<callback_t>;
// an example class with a member function to call
class foo {
public:
foo(const std::string& name) : instance_name(name) {}
void bar(void* something, ptrConstCComPortInfo_t c) {
std::cout << "foo::bar(" << instance_name << ") called\n"
"void* = " << something << "\n"
"ptrConstCComPortInfo_t = " << c << "\n";
}
private:
std::string instance_name;
};
// and a free function to call
void free_func(void* something, ptrConstCComPortInfo_t c) {
std::cout << "free_func_called\n"
"void* = " << something << "\n"
"ptrConstCComPortInfo_t = " << c << "\n";
}
int main() {
// some instances of the class
foo via_bind("called_via_bind");
foo via_lambda("called_via_lambda");
ptrConstCComPortInfo_t bork = nullptr; // dummy value
// a vector of callback subscribers
std::vector<function_t> subscribers{
&free_func,
std::bind(&foo::bar, &via_bind, std::placeholders::_1, std::placeholders::_2),
[&via_lambda](void* p, ptrConstCComPortInfo_t c) { via_lambda.bar(p, c); }
};
// perform callbacks
for(auto& cb : subscribers) {
cb(nullptr, bork);
}
}
Output:
free_func_called
void* = 0
ptrConstCComPortInfo_t = 0
foo::bar(called_via_bind) called
void* = 0
ptrConstCComPortInfo_t = 0
foo::bar(called_via_lambda) called
void* = 0
ptrConstCComPortInfo_t = 0
I am trying to implement a class that would allow listening on some events and when these emits are emitted, they would get notifications.
So i thought of using Functors,
class MyFunctor {
public:
virtual void emit() {}
vitual void compare() {}
};
class MyFunctorSpecial : public MyFunctor {
void (*)() ab;
public:
MyFunctorSpecial(void (*a)()) : ab(a) {}
void emit() { ab(); }
};
class EventEmitter {
std::map<std::string, std::vector<MyFunctor> > eventMap;
public:
void On(const std::string &, const MyFunctor &) {
// add to the map
}
void Emit(const std::string & eventName) {
// emit the event
// for all listeners in the vector for this event-name
// call the emit of them.
}
};
EventEmitter emitter;
// some function - abc()
MyFunctorSpecial funct(abc);
emitter.On("hello", funct);
emitter.Emit("hello");
But now i want to pass arguments to the listeners. Like
emitter.Emit("hello", 45, false);
I think that this information would be available to Emit() at compile time, about the data-types of the various arguments. Can i use that information to make it happen , using templates or anything.
If there is another kind of pattern for this problem? How can I do this?
The common design pattern for your problem is called the Observer Design-Pattern.
Your so called "functors" are not functors.
If so they would have implemented an operator () method, and could have been called like functions ( thus the name functor). Yours are not.
For example, this is a functor: ( notice the operator())
class MyFunctor
{
public:
void operator()(){};
};
try this simple example as follow:
class event_manager {
std::map<std::string, std::vector<std::function<void( std::string )>>> eventMap;
public:
void on( const std::string &evt_name, std::function<void( std::string )> listener ) {
auto it = eventMap.find( evt_name );
if ( it != eventMap.end( ) ) {
it->second.push_back( listener );
return;
}
eventMap[evt_name] = std::vector<std::function<void( std::string )>>( );
eventMap[evt_name].push_back( listener );
};
void emit( const std::string &evt_name, std::string data ) {
auto evts = eventMap.find( evt_name );
if ( evts == eventMap.end( ) ) return;
for ( std::vector<std::function<void( std::string )>>::iterator it = std::begin( evts->second ); it != std::end( evts->second ); ++it ) {
auto &func = *it;
func( data );
}
}
};
and subscribe and emit event as like:
event_manager evt_mng;
evt_mng.on( "data", [&]( auto res ) {
std::cout << res << std::endl;
} );
evt_mng.emit( "data", "Hello world" );
Consider the snippet:
# include <iostream>
# include <boost/scoped_ptr.hpp>
# include <boost/shared_ptr.hpp>
# include <boost/function.hpp>
# include <boost/array.hpp>
# include <boost/asio.hpp>
# include <boost/thread.hpp>
# include <boost/thread/locks.hpp>
# include <boost/bind.hpp>
# include <boost/noncopyable.hpp>
# include <boost/variant.hpp>
class DataLink {};
class Metadata {};
class Image {};
typedef boost::function<void( DataLink const&, Metadata const& , Image const& )> Handler ;
typedef boost::function<void( Metadata const& , Image const& )> Handler2 ;
typedef boost::function<void( Image const& )> Handler3 ;
typedef boost::variant<DataLink, Metadata, Image> Variant;
enum callbackHandler { link_enum, meta_enum, image_enum };
class Worker {
Handler callBack ;
//Handler2 callBack2 ;
//Handler3 callBack3 ;
DataLink dlink;
Metadata meta ;
Image img ;
callbackHandler handlerEnum ;
public :
Worker ( const Handler& handler )
: callBack ( handler )
{}
//Worker ( const Handler2& handler )
//: callBack2 ( handler )
// {}
//Worker ( const Handler3& handler )
//: callBack3 ( handler )
// {}
void Image ( ) {
// update the img object
// invoke call back
handlerEnum = image_enum ;
//const std::type_info& xxx = callBack.target_type();
//std::cout << xxx.raw_name() << std::endl;
callBack ( dlink, meta, img ) ;
}
void Metadata ( ) {
// update the meta object
// invoke call back
handlerEnum = meta_enum ;
callBack ( dlink, meta, img ) ;
}
void Dlink ( ) {
// update the link object
// invoke call back
handlerEnum = link_enum ;
callBack ( dlink, meta, img ) ;
}
callbackHandler getHandlerType() { return handlerEnum ; }
};
class Foo {
Worker *ptrWorker ;
public :
Foo ()
: ptrWorker( 0 )
{}
void callback ( DataLink const& d, Metadata const& m , Image const& i ) {
callbackHandler tt = ptrWorker->getHandlerType();
if ( tt == image_enum ) {
std::cout << "Image object " << std::endl;
}
if ( tt == meta_enum ) {
std::cout << "Meta object " << std::endl;
}
if ( tt == link_enum ) {
std::cout << "Link object " << std::endl;
}
}
bool start () {
ptrWorker = new ( std::nothrow ) Worker ( boost::bind ( &Foo::callback, this, _1, _2, _3 ) );
if ( !ptrWorker ) {
return - 1 ;
}
}
void testWorker() {
ptrWorker->Image() ;
ptrWorker->Metadata() ;
ptrWorker->Dlink() ;
}
};
int main() {
Foo f;
f.start() ;
f.testWorker() ;
std::cin.get() ;
}
The commented out constructors allows me to add support for Handler2 and Handler3, however is there a way to determine the handler that was passed to the constructor of the Worker class? At present the member functions Metadata, Image and Dlink use the 'callBack' object. I'll need to make a distinction if the user handler passed in another handler - say Handler2
The fact that I need to use enums to implement, what is effectively my own type-system (in the line of a discrimatory union - aka, a variant), is also a sure sign that the design needs a little re-thinking so in that case I'm open for a redesign. Having to have N-1 dummy handlers (ie, at any one time only one handler is being used and the others are just there doing nothing) defined in the class screams confused and low cohesive object model but who knows.
You could implement this using a functor, derived from a virtual base class:
struct CallbackBase
{
// Dummy virtual functions that does nothing
virtual operator()(DataLink const &, Metadata const &, Image const &) {}
virtual operator()(Metadata const &, Image const &) {}
virtual operator()(Image const &) {}
};
class Worker
{
CallbackBase &callback_;
public:
Worker(const CallbackBase &callback)
: callback_(callback)
{ }
void Image()
{
// Do something...
callback_(img);
}
void Metadata()
{
// Do something...
callback_(meta, img);
}
void Dlink()
{
// Do something...
callback_(dlink, meta, img);
}
};
struct MyCallback : public CallbackBase
{
virtual operator()(Image const &)
{
// Do something useful here
}
};
MyCallback my_callback;
Worker my_worker(my_callback);
Because of the overloads in the base callback class, the Worker class can call any of the of them in the correct place, while you only implement the callback you actually need in the derived callback class.
Here is the code I have...
struct Test {
string foo() { return "bar"; }
};
#define callFn(obj,method) obj->method();
int main() {
Test* t = new Test();
cout << callFn(t,foo); // bar
return 0;
}
...and here is the code I'd like to have
int main() {
Test* t = new Test();
string method = "foo";
cout << callFn(t,method); // bar
return 0;
}
Is it possible?
You can't. C++ doesn't have reflection capabilities.
You would have to define e.g. a std::map that maps strings to function pointers.
void foo(int x) { std::cout << "foo " << (x+3) << "\n"; }
void bar(int x) { std::cout << "bar " << (x+5) << "\n"; }
int main() {
std::map<std::string, void (*)(int)> mapper;
mapper["foo"] = &foo;
mapper["bar"] = &bar;
// ...
mapper["foo"](42);
mapper["bar"](42);
}
You probably want something like member function pointers:
typedef std::string (Test::*ptmf)();
#define CALL_MF(pobject, p) (((pobject)->*(p))())
int main()
{
ptmf method = &Test::foo;
Test * t = new Test;
std::string result = CALL_MF(t, method); // or directly: (t->*method)()
}
You can create containers whose elements are of type ptmf to manage different member function pointers at runtime:
std::map<int, ptmf> function_registry;
std::string call(int key, Test * t)
{
auto it = function_registry.find(key);
return (it != function_registry.end()) ? CALL_MF(t, *it) : "[ERROR]";
}
You can do something like this, but because C++ lacks reflection capabilities you have to do some extra work to make it possible.
struct base {
virtual void call_method( std::string const & ) = 0;
};
struct derived : public base {
std::string foo( ) const {
return "bar";
}
// More methods.
void call_method( std::string const &p_name ) {
if( p_name == "foo" ) {
this -> foo( );
}
// More checks on method names.
else {
// Handle invalid function name.
}
}
};
This is called a data-driven interface, where you pass commands to objects and they respond to the commands that they recognize in a polymorphic fashion. You can improve on what I showed by creating a statically initialized unordered map from commands to function pointer and then using that to resolve which function to call. It's good to avoid this type of function dispatch if you can, though, because it's slow in comparison to static function dispatch and error prone since typos may result incorrect calls or errors. It also has the downside that you can't get the return value easily, though it is possible in some cases.
EDIT: I wanted to give a more complete example of how this can be done, so here goes:
#include <cassert>
#include <iostream>
#include <boost/bind.hpp>
#include <boost/blank.hpp>
#include <boost/variant.hpp>
#include <boost/function.hpp>
#include <boost/unordered_map.hpp>
#include <boost/assign/list_of.hpp>
// A base class that defines an interface to call methods by name
// and to access the list of methods. We use a map of argument
// names to boost::variants to pass arguments to the functions.
// Right now we support only ints and strings, but we can expand
// this to other types if we want. In particular, we can use
// boost::any to support arbitrary types, but it will be slow.
// Maybe that's not a big deal since function dispatch through
// named functions is slow anyway.
struct base {
typedef boost::variant< boost::blank, int, std::string > argument_t;
typedef boost::variant< boost::blank, int, std::string > return_t;
typedef boost::unordered_map< std::string, argument_t > param_map_t;
typedef boost::function< return_t ( base *, param_map_t const & ) >
method_t;
typedef boost::unordered_map< std::string, method_t > method_map_t;
return_t call_method(
std::string const &p_method
, param_map_t const &p_params = param_map_t( )
)
{
method_map_t::const_iterator l_itr =
get_methods( ).find( p_method );
if( l_itr == get_methods( ).end( )) {
// Handle undefined method identifier.
}
return l_itr -> second( this, p_params );
}
virtual method_map_t const &get_methods( ) const = 0;
};
// A trampoline object to elide the concrete type that
// implements the base interface and to provide appropriate
// casting. This is necessary to force all functions in our
// method map to have the same type.
template< typename U >
base::return_t trampoline(
base::return_t (U::*p_fun)( base::param_map_t const & )
, base *p_obj
, base::param_map_t const &p_param_map
)
{
U *l_obj = static_cast< U* >( p_obj );
return (l_obj ->* p_fun)( p_param_map );
}
// A derived type that implements the base interface and
// provides a couple functions that we can call by name.
struct derived : public base {
static method_map_t const c_method_map;
return_t foo( param_map_t const &p_params ) {
std::cout << "foo" << std::endl; return 1;
}
return_t bar( param_map_t const &p_params ) {
std::cout << "bar" << std::endl; return std::string( "bar" );
}
method_map_t const &get_methods( ) const {
return c_method_map;
}
};
// Construct map of method names to method pointers for derived.
base::method_map_t const derived::c_method_map = boost::assign::map_list_of
( "foo", boost::bind( &trampoline< derived >, &derived::foo, _1, _2 ))
( "bar", boost::bind( &trampoline< derived >, &derived::bar, _1, _2 ))
;
int main( ) {
base *blah = new derived( );
// Call methods by name and extract return values.
assert( boost::get< int >( blah -> call_method( "foo" )) == 1 );
assert( boost::get< std::string >( blah -> call_method( "bar" )) == "bar" );
// Iterate over available methods
typedef base::method_map_t::const_iterator iterator;
iterator l_itr = blah -> get_methods( ).begin( );
iterator l_end = blah -> get_methods( ).end ( );
for( ; l_itr != l_end; ++l_itr ) {
if( l_itr -> first == "foo" ) l_itr -> second( blah, base::param_map_t( ));
}
}
The output is:
foo
bar
foo
As you can see it's quite a bit of work to set this up, but adding new types that implement the interface is pretty easy.
This is essentially the reflection mechanism that's available in post Java1.5
Here's an example of reflections in C++
http://www.garret.ru/cppreflection/docs/reflect.html
is there any way to declare a variety number of member variables from different user-data type generically using template operator?
consider this code:
class a {
int member;
void ProcessMemberVariable ();
};
class b {
char member;
void ProcessMemberVariable ();
};
... // arbitrary number of such classes
class test {
template <typename T>
void declare (T a ) {
// each time this member function is called a new member variable of the
// user data type T shall be declared in the instance of the class test??
}
};
int ()
{
test Test;
Test.template declare<a>(a A);
Test.template declare<b>(b B);
...
}
Imagine You want to implement an interface which is apple to set any kind of user defined data type. Since I know the identifier of user-defined data type only when I declare an instance of class "test" and call its member function...
I appreciate each suggestion..
What you are describing sounds like dynamically adding members to an object, and this isn't possible in C++. There are various ways to get a similar effect in certain situations, but you would need to describe a situation where you thought this would be useful.
As stated there is no way to dynamically add member variables at runtime.
However, if you know the list of types that you may want to add at runtime you could achieve this behaviour using boost::variant. Below is a trivial example (
#include <iostream>
#include <string>
#include <map>
#include <boost/variant.hpp>
using namespace std;
class Test
{
public:
typedef boost::variant< long, double, string > VariantType;
template< typename T >
void Declare( std::string name, T val )
{
VariantType newVal = val;
varMap.insert( std::make_pair( std::move( name ), std::move( val ) ) );
}
VariantType Get( const std::string& name )
{
return varMap[ name ];
}
template< typename T >
T GetValue( const std::string& name )
{
return boost::get<T>( varMap[name] );
}
private:
std::map< string, VariantType > varMap;
};
int main()
{
Test t{};
t.Declare( "Var1", 10l );
t.Declare( "pi", 3.14159);
t.Declare( "AString", "SomeName" );
cout << "t.get( Var1 ) " << t.GetValue<long>( "Var1" ) << "\n";
cout << "t.get( pi ) " << t.GetValue<double>( "pi" ) << "\n";
cout << "t.get( AString ) " << t.GetValue<string>( "AString" ) << "\n";
return 0;
}
See: http://www.boost.org/doc/libs/1_49_0/doc/html/variant.html for details on how to use boost::variant.