我正在尝试在C ++中实现有限的reflection
,这样我就可以在存储的对象上调用getter
和setter
。这是我到目前为止所做的事情
#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
这将被称为如下
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");
我已将getter
和setter
存储在map
中,但在put
函数中我无法调用它,因为我不知道该类型。
基本上我如何实现for循环for ( std::map< std::string, void*>::iterator itr = pos->second.begin(); itr != pos->second.end(); ++itr )
,其中我想迭代每个元素并调用相应的getter
和setter
方法。
我尝试了这个但是没有用。
(ptr->*((itr->second).m_Getter))();
我发现的另一种方法会感谢评论
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))();
}
}
}
答案 0 :(得分:1)
这些指针是{strong>指向Owner
类型的函数成员的指针:
get_func_t m_Getter;
set_func_t m_Setter;
为什么要尝试将SingleProperty<>
指针作为对象进行调用?
Owner *ptr = reinterpret_cast<Owner*>(value);
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;
// Here is the flaw, you are trying to call m_Getter from SingleProperty object
// pointer, but it must be Owner pointer!
(ptr->*m_Getter)();
}
此外,您必须正确传递属性类型作为模板参数IOType
。
我不确定你试图用这个函数做什么以及用废弃的返回类型调用getter的效果是什么,但从抽象语法的角度来看它应该是这样的:
template <class Owner, class IOType> void put(const std::string& key, Owner* value,
const std::string& class_name = "")
{
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,IOType> *ptr =
static_cast<SingleProperty<Owner, IOType>*>(itr->second);
(value->*(ptr->m_Getter))(); // return IOType discarded?!?!
}
}