samedi 8 août 2020

Function "Reflection" C++

I have the following code:

#include <iostream>
#include <string>
#include <map>
#include <type_traits>

namespace reflection {
    typedef void (*__unknown_func)();
    typedef std::pair<__unknown_func, size_t> __pair_type;

    std::map<std::string, __pair_type> functions;

    template<typename K, typename V>
    inline bool mapContains(const std::map<K, V>& __map, const K& __key) noexcept {
        return __map.find(__key) != __map.end();
    }

    template<typename _Ret, typename ... _Args>
    inline void addFunction(const std::string& function_name, _Ret (*__func)(_Args...)) noexcept {
        functions.insert_or_assign(function_name,
                std::move(__pair_type(std::move(reinterpret_cast<__unknown_func >(__func)), std::move(sizeof...(_Args)))));
    }

    template<typename _Ret, typename ... _Args>
    _Ret callFunction(const std::string& function_name, const _Args& ... arguments) {
        if (!mapContains(functions, function_name)) {
            // I handle here
        }

        if (sizeof...(_Args) != functions[function_name].second) {
            // I handle here
        }

        //  ------------ Any way to check if the argument are compatible here??? ------------

        if constexpr (std::is_same_v<_Ret, void>)
            reinterpret_cast<_Ret (*)(_Args...)>(functions[function_name].first)(arguments...);
        else
            return reinterpret_cast<_Ret (*)(_Args...)>(functions[function_name].first)(arguments...);
    }

}

int testFunction(long argument) {
    try {
        std::cout << "Success! Argument value: " << argument << std::endl;
    } catch (...) {
        return 0;
    }
    return 1;
}

int main(const int argc, const char* argv[]) {
    reflection::addFunction("run", testFunction);
    reflection::callFunction<int>("run", 93321);
    std::cin.get();
    return 0;
}

And it is completely functional.

Although, if I were not to call run with the wrong arguments:
i.e. like this:
reflection::callFunction("run", (std::vector<int>)93321);,
it would print out a random number as the "Argument value: " in testFunction.

I know it's because of the reinterpret_casts, since that's how that type of cast works, but I would still like to know if there is some type of workaround to this so that I can handle improper arguments.

Any help would be appreciated. Thanks!





Aucun commentaire:

Enregistrer un commentaire