dimanche 25 juin 2023

How to register classes without modifying main.cpp in C

I have a feature registration implementation, wherein new features can be added to the registry with a simple macro.

However, I want to follow Open-closed principle and NOT have to change the the main.cpp whenever a new feature is created, as their implementation details are not relevant for main.cpp.

The issue lies in the #include directive: If a feature file is not #included, the index for it does not exist in the scope. This is because each TYPE##Registered value exists only inside each header file, not inside the Register.h. But how can I get around this limitation?

To reiterate the question, How can I register features without modifying main.cpp for every new feature added?

main.cpp:

#include "Foo.h" // Must include, otherwise won't show up in registry!
#include "Bar.h"


int main()
{
    for (auto it : FeatureRegistry::GetInstance().GetFeatureRegistry())
    {
        printf(" registry: %s", it.first);
    }

    return 0;
}

Registry.h:

#pragma once

#include <cstddef>
#include <map>
#include <utility>


#define TYPE_REGISTER_ERROR 255 // Value not found in TypeRegistry

// Registers type into GlobalTypeRegistry
#define ENGINE_REGISTER_FEATURE(TYPE) class TYPE; static bool TYPE##Registered = \
    (FeatureRegistry::GetInstance().GetFeatureRegistry()[#TYPE] = \
    FeatureRegistry::GetInstance().GetFeatureRegistry().size(), true);

class FeatureRegistry
{
public:
    static FeatureRegistry& GetInstance()
    {
        static FeatureRegistry Instance;
        return Instance;
    }

    std::map<const char*, unsigned char>& GetFeatureRegistry()
    {
        static std::map<const char*, unsigned char> Registry;
        return Registry;
    }

    // Returns the value of the type in TypeRegistryMap
    unsigned char GetTypeIndex(const char* Classname)
    {
        auto it = GetFeatureRegistry().find(Classname);
        if (it != GetFeatureRegistry().end())
        {
            return it->second;
        }
        // Return a default value if the type is not found
        return TYPE_REGISTER_ERROR;
    }
};

#define TypeIndex(TYPE) \
    ([] { \
        class TYPE; \
        return FeatureRegistry::GetInstance().GetTypeIndex(#TYPE); \
    })()

Foo.h (Bar.h is identical)

#pragma once

#include "Register.h"

ENGINE_REGISTER_FEATURE(Foo)
class Foo
{

};

Aucun commentaire:

Enregistrer un commentaire