LINUX.ORG.RU

История изменений

Исправление KennyMinigun, (текущая версия) :

То, что ты делаешь называется интроспекцией. С++ крайне плох в этом плане (потому, что все резолвится статически на этапе компиляции).

Поэтому, что ты можешь сделать, это создать массив с лямбдами/std::function, которые будут дергать твою функцию правильно. Вот, например так (код чисто концептуальный, может даже нескомпилироваться):

// вот тут можно заюзать что-то более продвинутое, наподобии QVariant
typedef void * FunctionResult;
typedef void * FunctionArgument;

typedef std::map<std::string, FunctionArgument> FunctionArguments;
typedef std::function<FunctionResult (const FunctionArguments &)> FunctionHelper;

class MetaFunction {
public:
    MetaFunction(const std::string &name, FunctionHelper helper) :
        m_helper(helper),
        m_name(name)
    {}

    FunctionResult call(const FunctionArguments &args) {
        return this->m_helper(args);
    } 

private:
    std::string    m_name;
    FunctionHelper m_helper;
};

void* find_func(const std::string & name) { /* ... */ }

auto meta = MetaFunction("find_func", 
    [] (const FunctionArguments &args) -> FunctionResult {
        void *result = find_func(args["name"]);
        // тут надо подумать как конвертнуть результат в FunctionResult
        return FunctionResult(result); 
    }
);

auto result = meta.call({
    { "name", FunctionArgument("needle") }
});

Исправление KennyMinigun, :

То, что ты делаешь называется интроспекцией. С++ крайне плох в этом плане (потому, что все резолвится статически на этапе компиляции).

Поэтому, что ты можешь сделать, это создать массив с лямбдами/std::function, которые будут дергать твою функцию правильно. Вот, например так (код чисто концептуальный, может даже нескомпилироваться):

// вот тут можно заюзать что-то более продвинутое, наподобии QVariant
typedef void * FunctionResult;
typedef void * FunctionArgument;

typedef std::map<std::string, FunctionArgument> FunctionArguments;
typedef std::function<FunctionResult (const FunctionArguments &)> FunctionHelper;

class MetaFunction {
public:
    MetaFunction(const std::string &name, FunctionHelper helper) :
        m_helper(helper),
        m_name(name)
    {}

    FunctionResult call(const FunctionArguments &args) {
        return this->m_helper(args);
    } 

private:
    std::string    m_name;
    FunctionHelper m_helper;
};

void* find_func(const std::string & name) { /* ... */ }

auto meta = MetaFunction("find_func", 
    [] (const FunctionArguments &args) -> FunctionResult {
        void *result = find_func(args["name"]);
        // тут надо подумать как конвертнуть результат в FunctionResult
        return FunctionResult(result); 
    }
);

auto result = meta.call({
    { "name", "needle" }
});

Исходная версия KennyMinigun, :

То, что ты делаешь называется интроспекцией. С++ крайне плох в этом плане (потому, что все резолвится статически на этапе компиляции).

Поэтому, что ты можешь сделать, это создать массив с лямбдами/std::function, которые будут дергать твою функцию правильно. Вот, например так (код чисто концептуальный, может даже нескомпилироваться):

// вот тут можно заюзать что-то более продвинутое, наподобии QVariant
typedef void * FunctionResult;
typedef void * FUnctionArgument;

typedef std::map<std::string, FunctionArgument> FunctionArguments;
typedef std::function<FunctionResult (const FunctionArguments &)> FunctionHelper;

class MetaFunction {
public:
    MetaFunction(const std::string &name, FunctionHelper helper) :
        m_helper(helper),
        m_name(name)
    {}

    FunctionResult call(const FunctionArguments &args) {
        return this->m_helper(args);
    } 

private:
    std::string    m_name;
    FunctionHelper m_helper;
};

void* find_func(const std::string & name) { /* ... */ }

auto meta = MetaFunction("find_func", 
    [] (const FunctionArguments &args) -> FunctionResult {
        void *result = find_func(args["name"]);
        // тут надо подумать как конвертнуть результат в FunctionResult
        return FunctionResult(result); 
    }
);

auto result = meta.call({
    { "name", "needle" }
});