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);
Related
I have two functions which need to be exposed by the class and they look like this (more will follow):
void print_a(std::string s);
void print_b(std::string s, int val);
"Under the hood" they are doing the same exact thing namely doing a lookup in a map and passing the call parameters to the function pointer retrieved by the map:
#include <stdint.h>
#include <iostream>
#include <string>
#include <map>
class Thing{
private:
void do_a(){
std::cout << "hello";
}
//there might be also a method do_a_extended() which has a different key in the map
void do_b(int age){
std::cout << "my age is " << age;
}
typedef void (Thing::*do_stuff_a)();
typedef void (Thing::*do_stuff_b)(int);
std::map<std::string, do_stuff_a> a_table;
std::map<std::string, do_stuff_b> b_table;
public:
void print_a(std::string s){
do_stuff_a handler = a_table[s];
if(handler){
(this->*handler)();
}
}
void print_b(std::string s, int val){
do_stuff_b handler = b_table[s];
if(handler){
(this->*handler)(val);
}
}
};
I dislike the fact that there is a lot of boilerplate code involved. I wonder if its possible to pass a member into template so I can do this:
class Thing{
private:
void do_a(){
std::cout << "hello";
}
void do_b(int age){
std::cout << "my age is " << age;
}
typedef void (Thing::*do_stuff_a)();
typedef void (Thing::*do_stuff_b)(int);
std::map<std::string, do_stuff_a> a_table;
std::map<std::string, do_stuff_b> b_table;
template<<MAP_MEMBER>,typename ... PP>
void print_x(std::string s, PP &&... pp){
auto handler = <MAP_MEMBER>[s];
if(handler){
(this->*handler)(std::forward<PP>(pp) ...);
}
}
public:
typedef decltype(print_x<a_table>) print_a;
typedef decltype(print_x<b_table>) print_b;
};
Any ideas on how to get rid of boilerplate is appreciated.
No need to get complicated, just use your printers as wrappers that pass a member to a generic print method like so:
class Foo
{
int a;
char b;
template <typename M>
void Print (M & member)
{
// complicated function
}
public:
void PrintA ()
{
Print(a);
}
void PrintB ()
{
Print(b);
}
};
So in your example the public print functions become wrapper functions:
class Thing
{
// ...
template <typename T, typename ... PP>
void print (T & table, const std::string & key, PP && ... pp)
{
auto method = table[key];
if (method)
(this->*method)(std::forward<PP>(pp)...);
}
public:
template <typename ... PP>
void print_a (PP && ... pp)
{
print(a_table, std::forward<PP>(pp)...);
}
template <typename ... PP>
void print_b (PP && ... pp)
{
print(b_table, std::forward<PP>(pp)...);
}
};
These public methods should be inlined if you use -O3 optimisation.
Here's a running solution with less boilerplate and no need for metaprogramming:
#include <iostream>
#include <string>
#include <map>
class Thing
{
void do_a_1 ()
{
std::cout << "hello" << std::endl;
}
void do_a_2 ()
{
std::cout << "goodbye" << std::endl;
}
void do_b (int age)
{
std::cout << "my age is " << age << std::endl;
}
template <typename ... PP>
using MapMethod = std::map<std::string, void (Thing::*)(PP...)>;
MapMethod<> a_table;
MapMethod<int> b_table;
template <typename T>
void insert (T) {}
template <typename T, typename M, typename ... PP>
void insert (T & table, const std::string & key, M && method, PP && ... pp)
{
table.insert({key, method});
insert(table, pp...);
}
template <typename T, typename ... PP>
void print (const T & table, const std::string & key, PP && ... pp)
{
auto result = table.find(key);
if (result != table.end())
{
auto method = result->second;
(this->*method)(pp...);
}
}
public:
Thing ()
{
insert(a_table,
"apple", &Thing::do_a_1,
"banana", &Thing::do_a_2);
insert(b_table,
"ostrich", &Thing::do_b);
}
void print_a (const std::string & key)
{
print(a_table, key);
}
void print_b (const std::string & key, int val)
{
print(b_table, key, val);
}
};
int main ()
{
Thing t;
t.print_a("apple");
t.print_b("ostrich", 12);
t.print_a("banana");
t.print_a("Do nothing");
}
If somehow your wrapper methods are unavoidably repetitive in your real problem (perhaps perfect forwarding is getting tiresome), you could reduce boilerplate further with a macro to make the print methods:
class Thing
{
// private code is the same, except:
// there's no need for the generic print method anymore
public:
Thing ();
#define PRINT_MACRO(FUNCTION_NAME, MEMBER_TABLE) \
template <typename ... PP> \
void FUNCTION_NAME (const std::string & key, PP && ... pp) \
{ \
auto result = MEMBER_TABLE.find(key); \
if (result != MEMBER_TABLE.end()) \
{ \
auto method = result->second; \
(this->*method)(pp...); \
} \
}
PRINT_MACRO(print_a, a_table)
PRINT_MACRO(print_b, b_table)
#undef PRINT_MACRO
};
Lastly, are you sure that you wanted to use std::map instead of std::unordered_map? This problem suggests that you don't care about the ordering.
Macros or code generation are the way to go when you want to define things that require concatenating in identifiers.
In particular, since you also need to handle an arbitrary number of parameters in the generated code, I'd go with code generation.
You could extract the map to an extra class that can also handle searching and calling entries:
template <typename C, typename K, typename...Args>
class MemberFunctionCaller
{
private:
using FunctionType = void(C::*)(Args...);
using MapType = std::map<K, FunctionType>;
MapType registry;
public:
void Register(const K& key, FunctionType value)
{
registry[key] = value;
}
void Call(const K& key, C* self, const Args&...args)
{
auto iter = registry.find(key);
if(iter != registry.end())
{
FunctionType func = iter->second;
(self->*func)(args...);
}
}
};
A simple typedef would simplify the usage inside your "Thing"-class:
template <typename...Args>
using ThingFunctionCaller = MemberFunctionCaller<Thing, std::string, Args...>;
The thing class could look somewhat like this:
class Thing{
template <typename...Args>
using ThingFunctionCaller = MemberFunctionCaller<Thing, std::string, Args...>;
private:
void do_a(){
std::cout << "hello" << std::endl;
}
void do_b(int age){
std::cout << "my age is " << age << std::endl;
}
ThingFunctionCaller<> a_table;
ThingFunctionCaller<int> b_table;
public:
void print_a(std::string s){
a_table.Call(s, this);
}
void print_b(std::string s, int val){
b_table.Call(s, this, val);
}
};
And that's what it would look like in Action: https://gcc.godbolt.org/z/KM5a85
You could use a static template registry that stores the relation between name and member function.
This has other disadvantages but would work in your particular use case.
(With some additional coding you could even make this work more "natural").
template <typename C, typename...Args>
using MemberFunctionPointer = void(C::*)(Args...);
template <typename C, typename...Args>
class MemberFunctionCaller
{
private:
using FunctionType = MemberFunctionPointer<C, Args...>;
using MapType = std::map<std::string, FunctionType>;
static MapType& GetRegistry(){
static MapType registry;
return registry;
}
public:
static void Register(const std::string& key, FunctionType function)
{
auto& registry = GetRegistry();
registry[key] = function;
}
static void Call(const std::string& key, C* self, const Args&...args)
{
auto& registry = GetRegistry();
auto iter = registry.find(key);
if(iter != registry.end())
{
FunctionType func = iter->second;
(self->*func)(args...);
}
}
};
template <typename C>
class MemberFunctionRegistry
{
public:
template <typename...Args>
static void Register(const std::string& key, MemberFunctionPointer<C, Args...> function)
{
MemberFunctionCaller<C, Args...>::Register(key, function);
}
template <typename...Args>
static void Call(const std::string& key, C* self, const Args&...args)
{
MemberFunctionCaller<C, Args...>::Call(key, self, args...);
}
};
Your Thing class could look like this:
class Thing{
private:
void do_a(){
std::cout << "hello" << std::endl;
}
void do_a_extended(){
std::cout << "hello world" << std::endl;
}
void do_b(int age){
std::cout << "my age is " << age << std::endl;
}
MemberFunctionRegistry<Thing> registry;
public:
static void RegisterMemberFunctions()
{
MemberFunctionRegistry<Thing>::Register("A", &Thing::do_a);
MemberFunctionRegistry<Thing>::Register("AX", &Thing::do_a_extended);
MemberFunctionRegistry<Thing>::Register("B", &Thing::do_b);
}
template <typename...Args>
void print_x(std::string s, Args...args){
registry.Call(s, this, args...);
}
};
https://gcc.godbolt.org/z/fq5bez
I am trying to implement a general value class in C++ that can contain integer, float, and fractions, etc. So I wrote an interface value_interface and had int wrapped up in int_wrapper to inherit from the interface.
However, value(3) will not initialize a value object, because even if 3 is convertable to int_wrapper, which is convertable to value_interface, value_interface is not directly convertable to value. Is there a way to make value(3) possible? Or is there a better way to do this?
#include <string>
class value_interface {
public:
virtual std::string to_string() const = 0;
virtual ~value_interface() {}
};
class value {
std::shared_ptr<value_interface> d_ptr_;
public:
value(value_interface* x) { d_ptr_ = std::unique_ptr<value_interface>(x); }
std::string to_string() const { return d_ptr_->to_string(); }
};
class int_wrapper : public value_interface {
int val_;
public:
int_wrapper(const int val) : val_(val) {}
operator int() const { return val_; }
std::string to_string() const override { return std::to_string(val_); }
friend value operator+(int_wrapper x, int_wrapper y);
};
int main() {
value a = 3; // Error C2440 'initializing': cannot convert from 'int' to 'value'
int_wrapper b = 3; // ok
value_interface& c = static_cast<value_interface&>(b); // ok
value d = &c; // ok
return 0;
}
Create a make_value templated function with specialisations for each class. e.g:
template < typename T >
value make_value( const T& t );
template <>
value make_value< int >( const int& i )
{
return value{ std::make_shared< int_wrapper >( i ) };
}
Alternatively you can template the value constructor which will allow you to do value v = 3 directly:
class value {
std::shared_ptr<value_interface> d_ptr_;
public:
value(value_interface* x) { d_ptr_ = std::unique_ptr<value_interface>(x); }
template < typename T >
value( const T& t );
std::string to_string() const { return d_ptr_->to_string(); }
};
template <>
value::value< int >( const int& i )
:d_ptr_(std::make_shared<int_wrapper>(i))
{
}
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.
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 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... ]