I was trying to understand how std::function
works and created what started being a simple example:
#include <iostream>
#include <functional>
#include <string>
using namespace std::placeholders; // _1, _2, _3...
class holder
{
public:
using fn_decoder = std::function< int ( uint8_t input, int event ) >;
using raw_fn_decoder = int ( holder::* )( uint8_t input, int event );
fn_decoder _fn_decoder;
holder( )
: holder( std::bind( &holder::decode, this, _1, _2 ) )
{}
holder( raw_fn_decoder dec )
: _fn_decoder( std::bind( dec, this, _1, _2 ) )
{}
holder( fn_decoder dec )
: _fn_decoder( dec )
{}
virtual int decode( uint8_t input, int event )
{
std::cout << "[" << __PRETTY_FUNCTION__ << "] '" << input << "', " << ( unsigned )event << std::endl;
return event;
}
int operator( )( uint8_t input, int event )
{ return _fn_decoder( input, event ); }
};
int decode( uint8_t input, int event )
{
std::cout << "[" << __PRETTY_FUNCTION__ << "] '" << input << "', " << ( unsigned )event << std::endl;
return event;
}
int main( )
{
holder h0;
h0( 'A', 1 );
h0._fn_decoder = std::bind( &decode, _1, _2 );
h0( 'C', 3 );
}
And it outputs, as expected:
[virtual int holder::decode(uint8_t, int)] 65, 1
[int decode(uint8_t, int)] 67, 3
My next step was, then, add a derived class:
class new_holder
: public holder
{
public:
new_holder( )
: holder( static_cast< raw_fn_decoder >( &new_holder::decode ) )
{}
int decode( uint8_t input, int event )
{
std::cout << "[" << __PRETTY_FUNCTION__ << "] '" << input << "', " << ( unsigned )event << std::endl;
return event;
}
};
Then I added this lines to main()
:
new_holder h1;
h1( 'E', 5 );
h1._fn_decoder = std::bind( &holder::decode, &h1, _1, _2 );
h1( 'F', 6 );
h1._fn_decoder = std::bind( &decode, _1, _2 );
h1( 'G', 7 );
h0._fn_decoder = std::bind( &new_holder::decode, &h1, _1, _2 );
h0( 'B', 2 );
And the output:
[virtual int holder::decode(uint8_t, int)] 'A', 1 // As before.
[int decode(uint8_t, int)] 'C', 3 // As before.
[virtual int new_holder::decode(uint8_t, int)] 'E', 5 // As expected.
[virtual int new_holder::decode(uint8_t, int)] 'F', 6 // Shouldn't be holder::decode?
[int decode(uint8_t, int)] 'G', 7 // As expected.
[virtual int new_holder::decode(uint8_t, int)] 'B', 2 // Well, it is weird, but I asked for.
I cannot understand the 'F' line. I thought I should be able to build a std::function
out of holder::decode
since it is done in h0
construction.
Here is a live running example, for anyone willing to try out:
Things get even worse if I try to subclass new_holder
or derive another_holder
from holder
but I think it will get too verbose if I include it all here.
Thanks in advance