Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enumerate variadic template parameter pack

I have std::vector<val_t> (val_t - my own implementation of std::any) which holds arguments for function that I want to call and a parameter pack Args that contains types of arguments of that function.

using arg_pack_t = std::vector<val_t>;

template <typename R, typename... Args>
class function_reflector_t<R (*)(Args...)> {
    typedef R (*c_function_t)(Args...);
    using reflected_t = signature_reflector_t<R, Args...>;

  public:
    static function_metadata_t reflect(std::string name, c_function_t c_function)
    {
        // HERE! 
        universal_wrapper_t invoke = [](arg_pack_t args) -> val_t {
            return args[0].as<c_functon_t>()(args[??? + 1].as<Args>()...);
        };

        return {
            reinterpret_cast<void *>(c_function),
            nullptr,
            invoke,
            std::move(name),
            reflected_t::arguments(),
            reflected_t::return_type(),
        };
    }
};

To call this function I need to associate type of argument with index of same argument, so after all template instantiations are done compiler could generate an equivalent code to something like this:

universal_wrapper_t invoke = [](arg_pack_t args) -> val_t {
            return args[0].as<c_functon_t>()(args[1].as<int>(), args[2].as<double>());
        };

I read about std::integer_sequence but I couldn't come up with a way of using it in this case. Ideally I need some template like std::index_sequence_for that instead of size_t provides a type that has aliases to both index and type at that index, so it behaves kinda like python's enumerate.

like image 335
Islam Boziev Avatar asked Feb 28 '26 00:02

Islam Boziev


1 Answers

You might do somethig like that:

template <std::size_t ... Is>
static function_metadata_t reflect(std::string name,
                                   c_function_t c_function,
                                   std::index_sequence<Is...>)
{
    universal_wrapper_t invoke = [](arg_pack_t args) -> val_t {
        return args[0].as<c_functon_t>()(args[Is + 1].as<Args>()...);
    };

    return {
        reinterpret_cast<void *>(c_function),
        nullptr,
        invoke,
        std::move(name),
        reflected_t::arguments(),
        reflected_t::return_type(),
    };
}

static function_metadata_t reflect(std::string name, c_function_t c_function)
{
    return reflect(name, c_function, std::index_sequence_for<Args...>());
}
like image 88
Jarod42 Avatar answered Mar 01 '26 14:03

Jarod42



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!