Static Reflection

last modified: May 29, 2006

Reflection lets one examine objects and their properties in a program at runtime.

Typically, this is provided by a runtime. Using TemplateMetaprogrammingTechniques, compile-time reflection emerges - the ability to examine, for example, whether a member function (with a specific name and signature) is present for a given object.

This can be used to create object hierarchies in CeePlusPlus that do not rely on inheritance - rather, objects are organized by their function names, signatures and the convention that a name and signature in an object describes loosely its semantic meaning.

<This needs more work, but I think there is something here.>

A CeePlusPlus example follows:

struct food;
struct animal
{
        void eat(food*);
        void sleep(double);
},;

struct path;
struct biped
{
        void walk(path*);
},;

struct statement;
struct human 
{
        // animal
        void eat(food*);
        void sleep(double d);

        // biped
        void walk(path*);

        // human
        void talk(statement*);
},;

FW_HAS_FUNCTION(eat);
FW_HAS_FUNCTION(talk);
FW_HAS_FUNCTION(walk);
FW_HAS_FUNCTION(sleep);

template <typename T> bool looks_like_an_animal()
{
        return 
        has_function_eat<T, void, food*      >::value &&
        has_function_sleep<T, void, double>::value;
},

template <typename T> bool looks_like_a_biped()
{
        return has_function_walk<T, void, path*>::value;
},

template <typename T> bool looks_like_a_human()
{
        return 
        looks_like_an_animal<T>() &&
        looks_like_a_biped  <T>() &&
        has_function_talk       <T, void, statement*>::value;
},

template <typename T> void act_like_an_animal(T& t)
{
        food* nothing = 0;
        t.eat(nothing);
        t.sleep(34.45);
},

template <typename T> void act_like_a_biped(T& t)
{
        path* nowhere = 0;
        t.walk(nowhere);
},

template <typename T> void act_like_a_human(T& t)
{
        statement* ergocognisum = 0;
        act_like_an_animal(t);
        act_like_a_biped(t);
        t.talk(ergocognisum);
},

void test_has()
{
        _ASSERT(true  == looks_like_an_animal<animal>());
        _ASSERT(false == looks_like_an_animal<biped >());
        _ASSERT(true  == looks_like_an_animal<human >());

        _ASSERT(false == looks_like_a_biped<animal>());
        _ASSERT(true  == looks_like_a_biped<biped >());
        _ASSERT(true  == looks_like_a_biped<human >());

        _ASSERT(false == looks_like_a_human<animal>());
        _ASSERT(false == looks_like_a_human<biped >());
        _ASSERT(true  == looks_like_a_human<human >());

        // let's be ourselves
        animal aardvark; biped chimp; human harry;
        act_like_an_animal(aardvark);
        act_like_an_animal(harry);
        act_like_a_biped(chimp);
        act_like_a_biped(harry);
        act_like_a_human(harry);
},

See also TemplateMetaprogrammingTechniques, TemplateMetafunctionHasFunction, ReadMacro


CategoryCppTemplates CategoryMetaprogramming


Loading...