This is a simple delegate class that only works for methods of the format void ClassType::MethodType( InputType& ), but can easily be expanded to more generic functions, not shown simply because it would be too large.
class Delegate
{
public:
Delegate( void ) : Object( NULL ), Argument( NULL ) { }
virtual ~Delegate( void ) { }
template <class ClassType, class InputType, void (ClassType::*MethodType)( InputType )>
void Create( ClassType* SetObject, void* SetArgument = NULL )
{
Object = SetObject;
Argument = SetArgument;
StaticCall = &CallMethod<ClassType, InputType, MethodType>;
}
template <class InputType>
inline void operator()( InputType InputValue ) const
{
(*StaticCall)( Object, static_cast<void*>(InputValue) );
}
inline void operator()( void ) const
{
(*StaticCall)( Object, Argument );
}
protected:
typedef void (*FunctionCallType)( void*, void* );
void* Object;
void* Argument;
FunctionCallType StaticCall;
private:
template <class ClassType, class InputType, void (ClassType::*MethodType)( InputType )>
static inline void CallMethod( void* SetObject, void* PassArgument )
{
(static_cast<ClassType*>( SetObject )->*MethodType)( static_cast<InputType>(PassArgument) );
}
};
It's flexible and can be used to pool callback classes, but one problem I have with it is that so far it's on par with (or even slower when used in large vectors like I plan to) than a virtual call if it's used as a base class. I'm looking for any suggestions on how to increase performance since I'm out of ideas, even if it affects functionality.
The simplest performance measuring code I used (with -O3) was:
class VirtualBase
{
public:
virtual void TestCall( int* Data ) {}
};
class VirtualTest : public VirtualBase
{
public:
VirtualTest() : Value(0) {}
void TestCall( int* Data )
{
Value += *Data;
}
private:
int Value;
};
class DelTest : public Delegate
{
public:
DelTest() : Value(0)
{
Create<DelTest, int*, &DelTest::TestCall>( this );
}
void TestCall( int* Data )
{
Value += *Data;
}
private:
int Value;
};
int main( int argc, char **argv )
{
clock_t start;
int Value = 1;
VirtualBase* NewBase = new VirtualTest;
start = clock();
for( size_t Index = 0; Index < 1000000000; ++Index )
{
NewBase->TestCall( &Value );
}
delete NewBase;
std::cout << (( std::clock() - start ) / (double)CLOCKS_PER_SEC) << std::endl;
Delegate* NewDBase = new DelTest;
start = clock();
for( size_t Index = 0; Index < 1000000000; ++Index )
{
NewDBase->operator()( &Value );
}
delete NewDBase;
std::cout << (( std::clock() - start ) / (double)CLOCKS_PER_SEC) << std::endl;
return 0;
}
I should mention that I'd like the class to stay non-template, as it makes classes using callbacks to anything easy to iterate through in a single vector.
You might want to look at this Lightweight Generic C++ Callbacks article on CodeProject
Some of the code from the linked article, showing the use of a function template to do the forwarding:
template<typename R, typename P1, typename P2>
class Callback
{
public:
typedef R (*FuncType)(void*, P1, P2);
Callback() : func(0), obj(0) {}
Callback(FuncType f, void* o) : func(f), obj(o) {}
R operator()(P1 a1, P2 a2)
{
return (*func)(obj, a1, a2);
}
private:
FuncType func;
void* obj;
};
template<typename R, class T, typename P1, typename P2, R (T::*Func)(P1, P2)>
R Wrapper(void* o, P1 a1, P2 a2)
{
return (static_cast<T*>(o)->*Func)(a1, a2);
}
class Foo
{
public:
float Average(int n1, int n2)
{
return (n1 + n2) / 2.0f;
}
};
float Calculate(int n1, int n2, Callback<float, int, int> callback)
{
return callback(n1, n2);
}
int main()
{
Foo f;
Callback<float, int, int> cb
(&Wrapper<float, Foo, int, int, &Foo::Average>, &f);
float result = Calculate(50, 100, cb);
// result == 75.0f
return 0;
}
There is also a great write up on stackoverflow here which will give you better insight.
Related
struct PacketBase
{
virtual ~PacketBase() {}
template<class T>
const T& get() const
{
return static_cast<const PacketVal<T>&>(*this).val;
}
template<class T>
void set(const T& rhs)
{
return static_cast<PacketVal<T>>(*this).val = rhs;
}
};
template <typename T>
struct PacketVal : public PacketBase
{
T val;
PacketVal(const T& rhs) : val(rhs) {}
~PacketVal() {}
};
class CResponsePacket
{
private:
std::vector<std::pair<int, const PacketBase*>> m_vPacketData;
public:
void addValue(int n, const PacketBase& packetData)
{
m_vPacketData.emplace_back(std::make_pair(n, &packetData));
}
void print()
{
for ( auto& data : m_vPacketData )
{
std::printf("%d - ", data.first);
std::printf("%s\n", data.second->get<std::string>().c_str());
}
}
};
CResponsePacket has template class member-variable.
int main()
{
CResponsePacket packet;
std::string strAAA("AAA");
PacketVal<std::string> pVal(strAAA);
packet.addValue(1, pVal);
for ( int nIdx = 0; nIdx < 5; ++nIdx )
{
PacketVal<std::string> pp(strAAA);
packet.addValue(nIdx + 1, pp);
}
packet.print();
return 0;
}
The result is
1 - AAA
1 -
2 -
3 -
4 -
5 -
Because the instance is in a loop, memory is destroyed. But this is just an example, and I have to use loop actually. How can I solve this...?
......................
..................
You can make use of std::shared_pointer or std::unique_ptr (depending of your use), and so having the vector looking like this:
std::vector<std::pair<int, std::shared_pointer<PacketBase>>> m_vPacketData;
And so then the addValue method should look like this:
void addValue(int n, const PacketBase& packetData)
{
m_vPacketData.emplace_back(
std::make_pair(
n,
std::make_shared<PacketBase>(packetData)
)
);
}
This will make a copy of packetData on the heap, and store the reference in a shared pointer. If you don't what this copy to be made, then you have to define a new constructor in PacketBase
class PacketBase{
public:
PacketBase(PacketBase&& el): attr(std::move(el.attr))... {...}
}
and then redefining the addValue that accept a rvalue reference
void addValue(int n, PacketBase&& packetData)
{
m_vPacketData.emplace_back(
std::make_pair(
n,
std::make_shared<PacketBase>(std::move(packetData))
)
);
}
And then actually calling the right addValue from main:
for ( int nIdx = 0; nIdx < 5; ++nIdx )
{
PacketVal<std::string> pp(strAAA);
packet.addValue(nIdx + 1, std::move(pp));
}
Or actually just:
for ( int nIdx = 0; nIdx < 5; ++nIdx )
packet.addValue(nIdx + 1, PacketVal<std::string>(strAAA););
This will obviously force you to rewrite the entire class, because you are changing the attribute type... the other way that you can achieve this is switch from
m_vPacketData.emplace_back(std::make_pair(n, &packetData));
to
m_vPacketData.emplace_back(std::make_pair(n, new PacketVal(packetData)));
But you have then remember to delete the objects on the heap or you will have memory leaks
Is there anyways to fusion::for_each() to iterate through a1 and a2 in a BOOST_FUSION_ADAPT_ADT or BOOST_FUSION_ADAPT_ASSOC_ADT, just like if adapted using BOOST_FUSION_ADAPT_STRUCT?
class A
{
private:
int a1_;
double a2_;
public:
void set_a1(int v) { a1_ = v; }
int get_a1() const { return a1_; }
void set_a2(double v) { a2_ = v; }
double get_a2() const { return a2_; }
};
BOOST_FUSION_ADAPT_ASSOC_ADT(
A,
(int, int, obj.get_a1(), obj.set_a1(val) )
(double, double, obj.get_a2(), obj.set_a2(val) )
)
struct Print
{
template <typename T>
void operator()( T& t ) const
{
// T is of type adt_attribute_proxy
// cout << ??
// would like to print a1 and a2 value
}
};
int main()
{
A a;
boost::fusion::for_each( a, Print() );
}
adt_attribute_proxy provides method get to access attribute value.
struct Print
{
template <typename T>
void operator()(T& t) const
{
std::cout << t.get();
}
};
P.S. There are errors in you sample BOOST_FUSION_ADAPT_ASSOC_ADT macro. Each element should be declared with 5 params (attribute_typeN, attribute_const_typeN, get_exprN, set_exprN, key_typeN) Maybe you mix up BOOST_FUSION_ADAPT_ASSOC_ADT with BOOST_FUSION_ADAPT_ADT?
I would like to define a new function in muParser Link.
The FunctionWrapper-Class should be registrated.
class FunctionWrapper
{
public:
virtual double Evaluate(const double*, int) = 0;
};
The DefineFun-Method needs a string and a function pointer. How can I make this pointer to the function Evaluate?
I would like to call the DefineFun in an other class... something like this:
bool OtherClass::RegisterFunction(std::string name, FunctionWrapper *wrapper)
{
fParser.DefineFun(name, wrapper->????);
}
THx
Have you considered std::function as your wrapper? In conjunction with std::bind or lambdas, it can probably do everything you need. E.g.,
#include <unordered_map>
#include <functional>
#include <exception>
#include <memory>
#include <string>
#include <iostream>
class Evaluator
{
public:
virtual ~Evaluator() {}
virtual double Evaluate( const double*, int ) = 0;
// ...
};
class Registry
{
public:
typedef std::function<double(const double*, int)> Fn; // For easier reading
class NameNotFoundException : public std::exception {};
void Register( const std::string& name, const Fn& fn )
{
_regMap[ name ] = fn;
}
void Call( const std::string& name, const double* const data, const int size )
{
auto it = _regMap.find( name );
if( it == _regMap.end() )
{
throw NameNotFoundException();
}
it->second( data, size ); // Call fn
}
private:
std::unordered_map<std::string, Fn> _regMap;
};
class EvaluatorImpl : public Evaluator
{
public:
double Evaluate( const double* const data, const int size )
{ /*...*/
for( int n=0; n < size; ++n )
std::cout << data[n] << '\n';
return 0;
}
// ...
};
int main()
{
std::shared_ptr<Evaluator> eval( new EvaluatorImpl() );
Registry reg;
// Could use a lambda here instead of std::bind
reg.Register( "Bob",
std::bind( &Evaluator::Evaluate, eval, std::placeholders::_1, std::placeholders::_2 ) );
const double data[] = { 1, 2, 3 };
int size = 3;
reg.Call( "Bob", data, size );
}
here a sample Code:
#include <functional>
#include "muParser.h"
class Evaluator
{
public:
virtual ~Evaluator() {}
virtual double Evaluate( const double*, int ) = 0;
// ...
typedef std::function<double(const double*, int)> Fn; // For easier reading
};
class EvaluatorImpl : public Evaluator
{
public:
double Evaluate( const double* const data, const int size )
{ return 0; }
};
void MyClass::test()
{
Evaluator *e = new EvaluatorImpl();
Evaluator::Fn fn = std::bind( &Evaluator::Evaluate, e, std::placeholders::_1, std::placeholders::_2 );
mu::Parser fParser;
fParser.DefineFun("test", fn);
}
I get no matching function for call to mu::ParserCallback::ParserCallback(std::function<double(const double*, int)>&, bool&)’ when I call DefineFun(string, T a_func)
I am trying to find a class hierarchy that permits to implement place holders for processor registers and operations on it. It should also allow for constants to be folded at run time. For sake of simplicity I'll only look at one operation, here multiplication. Place holders and constants should be accessible uniformly, i.e. have a common base class.
The code below defines the following classes:
class A: Base class for place holders (registers) and constants
class B: Place holder for a register (its structure holds the name of it)
class C: Base of all constants
class CI: int constant
class CF: float constant
#include <iostream>
#include <memory>
#include <cassert>
class A {
public:
virtual ~A(){}
};
class B : public A {
};
class C : public A {};
class CI : public C {
public:
typedef int Type_t;
int getValue() {return 1;}
};
class CF : public C {
public:
typedef float Type_t;
float getValue() {return 1.1;}
};
typedef std::shared_ptr<A> Aptr;
typedef std::shared_ptr<B> Bptr;
typedef std::shared_ptr<C> Cptr;
typedef std::shared_ptr<CI> CIptr;
typedef std::shared_ptr<CF> CFptr;
template<class T, class T2> struct promote {};
template<> struct promote<float,int> { typedef float Type_t; };
template<> struct promote<float,float> { typedef float Type_t; };
template<> struct promote<int,float> { typedef float Type_t; };
template<> struct promote<int,int > { typedef int Type_t; };
template<class T1, class T2>
typename promote<typename T1::element_type::Type_t,
typename T2::element_type::Type_t>::Type_t
mul_const( const T1& c1 , const T2& c2 )
{
std::cout << c1->getValue() * c2->getValue() << "\n";
return c1->getValue() * c2->getValue();
}
template<class T>
std::shared_ptr<T> get(const Aptr& pA) {
return std::dynamic_pointer_cast< T >( pA );
}
Aptr create_A(float f) { return std::make_shared<A>(); }
Aptr create_A(int i) { return std::make_shared<A>(); }
Aptr mul_const( const Cptr& cp1 , const Cptr& cp2 )
{
if (auto c1 = get<CI>(cp1))
if (auto c2 = get<CF>(cp2)) {
return create_A( mul_const(c1,c2) );
}
if (auto c1 = get<CF>(cp1))
if (auto c2 = get<CI>(cp2)) {
return create_A( mul_const(c1,c2) );
}
if (auto c1 = get<CI>(cp1))
if (auto c2 = get<CI>(cp2)) {
return create_A( mul_const(c1,c2) );
}
if (auto c1 = get<CF>(cp1))
if (auto c2 = get<CF>(cp2)) {
return create_A( mul_const(c1,c2) );
}
assert(!"oops");
}
Aptr mul( const Aptr& pA1, const Aptr& pA2 )
{
if (auto c1 = get<C>(pA1))
if (auto c2 = get<C>(pA2))
{
return mul_const(c1,c2);
}
}
int main()
{
Aptr pA1( new CF );
Aptr pA2( new CI );
Aptr result = mul( pA1, pA2 );
}
The problem I am having with the above code is the function Aptr mul_const( const Cptr& cp1 , const Cptr& cp2 ). It contains basically switching of types for all possible combinations of constant types. It works, but I would like to know if this can be done more elegantly?
I guess you could do what the compiler does, and convert the other parameter to float when one is float. You'll probably need a new function to do the conversion and a "isFloat" (or "isInt"). I'm not convinced it gives you that much benefit, really...
// Add two virtual member functions here:
class C : public A {
public:
virtual bool isInt() = 0;
virtual float getAsFloat() = 0;
};
Then implement:
class CI : public C {
public:
typedef int Type_t;
int getValue() {return 1;}
float getAsFloat() { return getValue(); }
bool isInt() { return true; }
};
class CF : public C {
public:
typedef float Type_t;
float getValue() {return 1.1;}
float getAsFloat() { return getValue(); }
bool isInt() { return false; }
};
Now, your mul_const becomes:
Aptr mul_const( const Cptr& cp1 , const Cptr& cp2 )
{
if (cp1.isInt() && cp2.isInt())
{
CIptr c1 = get<CI>(cp1));
CIptr c2 = get<CI>(cp2));
std::cout << c1->getValue() * c2->getValue() << "\n";
return CIptr(c1->getValue() * c2->getValue());
}
else
{
std::cout << cp1->getAsFloat() * cp2->getAsFloat() << "\n";
return CFptr(cp2->getAsFloat() * cp2->getAsFloat());
}
// This becomes unreachable... Probably OK to delete.
assert(!"oops");
}
[And I think a few template parts can be deleted... ]
Basically, I have lots of differently typed structs like this:
typedef struct
{
char memberA;
int memberB;
...
} tStructA;
Is it possible to use a template to get/extract an arbitrary member from the struct? In pseudocode, I'm looking for something like this:
/*This is pseudocode!*/
template <typename STRUCT_TYPE, typename MEMBER_TYPE, membername NAME>
class cMemberExtractor
{
public:
MEMBER_TYPE
extract(const STRUCT_TYPE* pStruct) const
{
return pStruct->NAME;
}
};
The idea behind is to use the template like this:
/*somewhere*/
void
producer()
{
//produce update
tStructA* pUpdate=new tStructA;
...
//send update to receivers
emit(pUpdate);
}
/*elsewhere*/
void
consumer(const tStructA* pUpdate)
{
//extract data
int data=cMemberExtractor<tStructA,int,memberB>().extract(pUpdate);
//process data
...
}
Thanks for your help!
You can do that not with names but with member pointers:
template <typename C, typename M>
struct updater_t {
typedef M C::*member_ptr_t;
updater_t( member_ptr_t ptr, M const & new_value )
: new_value( new_value ), ptr(ptr)
{}
updater_t( member_ptr_t ptr, C & original )
: new_value( original.*ptr ), ptr(ptr)
{}
void operator()( C & obj ) {
obj.*ptr = new_value;
}
M new_value;
member_ptr_t ptr;
};
struct test {
int value;
};
int main() {
updater_t<test,int> update( &test::value, 10 );
test object;
update( object );
test object2;
updater_t<test,int> update_copy( &test::value, object );
update_copy( object2 );
}
Edit: Moving the member pointer to a template argument as suggested by litb:
template <typename C, typename M, M C::* Ptr>
struct updater_t {
updater_t( M const & new_value ) : new_value( new_value ) {}
updater_t( member_ptr_t ptr, C & original ) : new_value( original.*Ptr ) {}
void operator()( C & obj ) {
obj.*ptr = new_value;
}
M new_value;
};
int main() {
updater_t<test,int, &test::value> update( 10 );
test object;
update( object );
}
This works for me:
#include <iostream>
struct Foo {
int member;
Foo() : member() {}
};
template< typename T, typename C >
T& extract(C& obj, T C::* member)
{
return (obj.*member);
}
int main()
{
Foo foo;
std::cout << foo.member << '\n';
extract(foo, &Foo::member) = 42;
std::cout << foo.member << '\n';
return 0;
}
extract(Object, &Class::Member) returns a reference to Member in Object. Is that what you wanted?
You need help from macros.
#include <cstddef>
template <typename StructType, typename MemberType, size_t member_offset>
struct cMemberExtractor {
MemberType extract(const StructType* pStruct) const {
const char* member_loc = reinterpret_cast<const char*>(pStruct) + member_offset;
return *(reinterpret_cast<const MemberType*>(member_loc));
}
};
#define M_MEMBER_EXTRACTOR(STRU, MEMTYPE, MEMNAME) \
(cMemberExtractor<STRU,MEMTYPE,offsetof(STRU,MEMNAME)>())
...
int data = M_MEMBER_EXTRACTOR(tStructA,int,memberB).extract(pUpdate);
If your compiler supports the typeof operator, the MEMTYPE argument can be eliminated to help type safety.
#define M_MEMBER_EXTRACTOR(STRU, MEMNAME) \
(cMemberExtractor<STRU,typeof(((STRU*)0)->MEMNAME),offsetof(STRU,MEMNAME)>())
...
int data = M_MEMBER_EXTRACTOR(tStructA,memberB).extract(pUpdate);