/*
 * c++类反射
 */

#ifndef INC_ENGINE_FACTORY_H
#define INC_ENGINE_FACTORY_H

#include <string>
#include <map>
#include <functional>

//引擎注册宏
#define ENGINE_REGIST(class_name)                                                             \
    namespace ai_matrix                                                                     \
    {                                                                                         \
        class class_name##Helper                                                              \
        {                                                                                     \
        public:                                                                               \
            class_name##Helper()                                                              \
            {                                                                                 \
                EngineFactory::RegisterEngine(#class_name, class_name##Helper::CreatObjFunc); \
            }                                                                                 \
            static void *CreatObjFunc()                                                       \
            {                                                                                 \
                return new class_name;                                                        \
            }                                                                                 \
        };                                                                                    \
        static class_name##Helper class_name##helper;                                         \
    }

namespace ai_matrix
{
    using Constructor = std::function<void *()>;

    class EngineFactory
    {
    public:
        static void RegisterEngine(std::string className, Constructor constructor)
        {
            Constructors()[className] = constructor;
        }

        static void *MakeEngine(const std::string &className)
        {
            auto itr = Constructors().find(className);
            if (itr == Constructors().end())
            {
                return nullptr;
            }
            return ((Constructor)itr->second)();
        }

    private:
        inline static std::map<std::string, Constructor> &Constructors()
        {
            static std::map<std::string, Constructor> instance;
            return instance;
        }
    };
}

#endif