Skip to content

Instantly share code, notes, and snippets.

@remram44
Created January 20, 2014 20:21
Show Gist options
  • Select an option

  • Save remram44/8528304 to your computer and use it in GitHub Desktop.

Select an option

Save remram44/8528304 to your computer and use it in GitHub Desktop.
Object registry
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
set(CMAKE_CXX_FLAGS "-g -Wall")
PROJECT(mark_fields)
# Sets up project-wide include dirs
INCLUDE_DIRECTORIES("${PROJECT_SOURCE_DIR}")
INCLUDE_DIRECTORIES("${PROJECT_BINARY_DIR}")
# Builds proxychain tool
ADD_EXECUTABLE(test main.cpp registered_object.cpp)
#include "registered_object.h"
#include <iostream>
#include <string>
class MyObject : public RegisteredObject {
protected:
int x, y;
std::string name;
public:
MyObject(int x_, int y_, const std::string &name_)
: x(x_), y(y_), name(name_)
{
}
BEGIN_FIELDS(MyObject);
REGISTER_FIELD(x, "X coordinate");
REGISTER_FIELD(y, "Y coordinate");
REGISTER_FIELD(name, "Some meaningful name");
END_FIELDS(MyObject);
};
REGISTER_OBJECT(MyObject);
int main()
{
MyObject m(4, 2, "Hello");
print_fields(&m);
print_classes();
std::cout << "meta gives: \"" << get_meta("MyObject")->getClassname()
<< "\"" << std::endl;
return 0;
}
#include "registered_object.h"
#include <iostream>
std::map<std::string, const MetaObject *(*)()> ObjectRegistrar::classes;
ObjectRegistrar::ObjectRegistrar(const std::string &name, const MetaObject *(*gmo)())
{
classes[name] = gmo;
}
void print_fields(const RegisteredObject *o)
{
const MetaObject *meta = o->getMetaObjectInst();
const std::vector<Field*> &fields = meta->getFields();
std::vector<Field*>::const_iterator it;
std::cout << "Fields for " << meta->getClassname() << std::endl;
for(it = fields.begin(); it != fields.end(); ++it)
{
Field &f = **it;
std::cout << " " << f.name << " (" << f.description
<< "): " << f.getValue(o) << std::endl;
}
}
void print_classes()
{
std::map<std::string, const MetaObject *(*)()>::const_iterator it;
it = ObjectRegistrar::classes.begin();
std::cout << "Registered classes:" << std::endl;
for(; it != ObjectRegistrar::classes.end(); ++it)
std::cout << " " << it->first << std::endl;
}
const MetaObject *get_meta(const char *classname)
{
std::map<std::string, const MetaObject *(*)()>::const_iterator it;
it = ObjectRegistrar::classes.find(classname);
if(it != ObjectRegistrar::classes.end())
return it->second();
else
return 0;
}
#ifndef REGISTERED_OBJECT_H
#define REGISTERED_OBJECT_H
#include <map>
#include <sstream>
#include <vector>
#define BEGIN_FIELDS(c) \
private: \
typedef c __Object_type; \
virtual const MetaObject *getMetaObjectInst() const \
{ \
return c::getMetaObject(); \
} \
public: \
static const MetaObject *getMetaObject() \
{ \
static MetaObject *i = 0; \
if(i == 0) \
{ \
i = new MetaObject(#c)
#define REGISTER_FIELD(f, descr) \
i->addField(#f, &__Object_type::f, descr)
#define END_FIELDS(c) \
} \
return i; \
} \
private: \
typedef int __Object_dummy
class RegisteredObject;
class MetaObject;
class ObjectRegistrar {
public:
static std::map<std::string, const MetaObject *(*)()> classes;
public:
ObjectRegistrar(const std::string &name, const MetaObject *(*gmo)());
};
#define REGISTER_OBJECT(c) ObjectRegistrar c##_reg(#c, &c::getMetaObject)
class Field {
public:
const char *const name;
const char *const description;
virtual std::string getValue(const RegisteredObject *o) const = 0;
protected:
Field(const char *n, const char *d)
: name(n), description(d)
{
}
};
template<class C, typename T>
class ActualField : public Field {
private:
T C::*ptr;
public:
ActualField(const char *n, const char *d, T C::*p)
: Field(n, d), ptr(p)
{
}
std::string getValue(const RegisteredObject *o) const
{
const C *c = static_cast<const C*>(o);
std::ostringstream oss;
oss << c->*ptr;
return oss.str();
}
};
class MetaObject {
private:
const char *const m_Classname;
std::vector<Field*> m_Fields;
public:
MetaObject(const char *classname)
: m_Classname(classname)
{
}
template<class C, typename T>
void addField(const char *name, T C::*ptr, const char *description)
{
m_Fields.push_back(new ActualField<C, T>(name, description, ptr));
}
const char *const getClassname() const
{
return m_Classname;
}
const std::vector<Field*> &getFields() const
{
return m_Fields;
}
};
class RegisteredObject {
public:
virtual const MetaObject *getMetaObjectInst() const = 0;
};
void print_fields(const RegisteredObject *o);
void print_classes();
const MetaObject *get_meta(const char *classname);
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment