C ++中的一种反思

时间:2012-11-01 10:20:05

标签: c++ oop reflection

我正在尝试在C ++中实现有限的reflection,这样我就可以在存储的对象上调用gettersetter。这是我到目前为止所做的事情

主要代码

#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");

我已将gettersetter存储在map中,但在put函数中我无法调用它,因为我不知道该类型。

问题

基本上我如何实现for循环for ( std::map< std::string, void*>::iterator itr = pos->second.begin(); itr != pos->second.end(); ++itr ),其中我想迭代每个元素并调用相应的gettersetter方法。

我尝试了这个但是没有用。

(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))();
        } 
    }
  }

1 个答案:

答案 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?!?!
    }
}