I am trying to implement limited reflection in C++, so that I could be able to call getter and setter on the objects stored. Here is what I have done so far
Main Code
#ifndef REFLECTION_MANAGER_HPP_
#define REFLECTION_MANAGER_HPP_
#include <iostream>
#include <string>
template <class Owner, class IOType>
class SingleProperty {
public:
typedef IOType (Owner::*get_func_t)();
typedef void (Owner::*set_func_t)( IOType Value );
inline SingleProperty(get_func_t Getter, set_func_t Setter ): m_Getter(Getter), m_Setter(Setter) {
}
get_func_t m_Getter;
set_func_t m_Setter;
};
class ReflectionManager {
public:
static ReflectionManager& Instance() {
static ReflectionManager instance;
return instance;
}
template <class Owner, class IOType>
void RegisterProperty( std::string class_name,
std::string property_name,
typename SingleProperty<Owner, IOType>::get_func_t GetFn,
typename SingleProperty<Owner, IOType>::set_func_t SetFn) {
SingleProperty<Owner, IOType>* pProperty = new SingleProperty<Owner, IOType>(GetFn, SetFn );
m_class_memeber_map[class_name][property_name] = pProperty;
}
template <class Owner> void put(std::string key, void *value, std::string class_name = NULL ) {
Owner *ptr = reinterpret_cast<Owner*>(value);
std::map<std::string, std::map< std::string, void*> >::iterator pos = m_class_memeber_map.find(class_name);
if ( pos == m_class_memeber_map.end()) {
return; // handle the error
}
for ( std::map< std::string, void*>::iterator itr = pos->second.begin(); itr != pos->second.end(); ++itr ) {
SingleProperty<Owner,std::string> *ptr = (SingleProperty<Owner,std::string> *)itr->second;
(ptr->*m_Getter)();
}
}
private:
ReflectionManager() {
}
ReflectionManager(ReflectionManager const&);
void operator=(ReflectionManager const&);
std::map<std::string, std::map< std::string, void*> > m_class_memeber_map;
};
#endif
Calling Code
This will be called as follows
ReflectionManager::Instance().RegisterProperty<Person, std::string>("Person", "m_name", &Person::GetName, &Person::SetName);
ReflectionManager::Instance().RegisterProperty<Person, std::string>("Person", "m_dept", &Person::GetDept, &Person::SetDept);
ReflectionManager::Instance().RegisterProperty<Person, int>("Person", "m_age", &Person::GetAge, &Person::SetAge);
Person p1;
p1.SetName("Avinash");
p1.SetDept("Gemfire Native Client");
p1.SetAge(34);
ReflectionManager::Instance().put<Person>( "key1", &p1, "Person");
I have stored the getter and setter in the map, but in put function I am not able to call it since I donot know the type.
Problem
Basically How do i implement now the for loop for ( std::map< std::string, void*>::iterator itr = pos->second.begin(); itr != pos->second.end(); ++itr ) in which I want to iterate over each element and call the respective getter and setter methods.
I tried this but does not work.
(ptr->*((itr->second).m_Getter))();
Another Approach I found Would appreciate Comments
template <class Owner, class IOType>
void RegisterProperty( std::string class_name,
std::string property_name,
typename SingleProperty<Owner, IOType>::get_func_t GetFn,
typename SingleProperty<Owner, IOType>::set_func_t SetFn) {
SingleProperty<Owner, IOType>* pProperty = new SingleProperty<Owner, IOType>(GetFn, SetFn );
m_class_memeber_map[class_name][property_name] = pProperty;
m_property_type_map[class_name].push_back(std::make_pair(property_name, TypeName<IOType>::get()));
}
template <class Owner> void put(std::string key, void *value, std::string class_name = NULL ) {
Owner *pOwner = reinterpret_cast<Owner*>(value);
std::map<std::string, std::map< std::string, void*> >::iterator pos = m_class_memeber_map.find(class_name);
std::vector<std::pair<std::string, std::string> > vector_property_map = m_property_type_map.find(class_name)->second;
for ( std::vector<std::pair<std::string, std::string> >::iterator itr = vector_property_map.begin();itr != vector_property_map.end(); ++itr ) {
std::map< std::string, void*>::iterator pos_getter_setter_fn = pos->second.find(itr->first);
if ( itr->second == "int" ) {
SingleProperty<Owner,int> *ptr = (SingleProperty<Owner, int> *)pos_getter_setter_fn->second;
(pOwner->*(ptr->m_Getter))();
} else if ( itr->second == "string" ) {
SingleProperty<Owner,std::string> *ptr = (SingleProperty<Owner, std::string> *)pos_getter_setter_fn->second;
(pOwner->*(ptr->m_Getter))();
}
}
}
These pointers are pointers to function members of
Ownertype:Why do you try to call them giving
SingleProperty<>pointer as object?Also you have to properly pass type of property as template parameter
IOType.I’m not sure what do you try to do with this function and what is the effect of calling getters with discarded return type, but from abstract syntax point of view it shall be like this: