Search code examples
c++c++11variadic-templatestemplate-argument-deductiontuple-packing

C++, match custom placeholders with function arguments


I am trying to write the piece of code which will do the following: let's assume we have a call of custom bind function

auto bind_obj = bind(some_func, _1, "test")  

and after we have

auto res = bind_obj(42) 

where the function some_func:

int some_func(int val, string test)

How can it possible to match placeholders with arguments provided in actual function call, i.e. bind_obj(...)??

In other words, is it possible to iterate over std::tuple (arguments and placeholders here) and variadic pack (function arguments) to:

  1. deduce the return type of function some_func;
  2. make correct std::tuple to further use it in some_func() call ?

I am trying to do this not using boost and std::functional. I think, my main problem is that i don't understand how to build tuple at runtime with arguments (where all the placeholders replaced correctly) and to deduce return type.

I saw _Mu template structure in STL "functional.h" but it looks too complex and overloaded.


Solution

  • Since the argument list of the call and list of captured arguments are differently sized, you won't really iterate over them. Instead, you'd get a function evaluated which behaves according to how arguments were captured:

    • if the bound element is a value it returns the value
    • if the bound element is a placeholder it returns the argument at the given index
    • if the bound element is a bind function it returns the result of evaluating this function

    Assume your bound object contains a std::tuple<B...> of bound arguments called b then you could construct a std::tuple<...> of call arguments something like this:

    template <typename... A, std::size_t... I>
    ... bound::call(std::tuple<A...>&& aux, index_list<I...>) {
        auto args = std::make_tuple(get_argument<I>(this->b, a));
        // ...
    }
    template <typename... A>
    ... bound::operator()(A&&... args) {
        return this->call(std::tie(std::forward<A>(args)..., make_index_list<sizeof...A>());
    }
    

    This code snippet just shows how to get the arguments sort of matched up. The real work happens in the get_argument<I>(b, a) functions which woild just return the element of a indicated by the placeholder's value if the element at index I in b happens to be a placeholder.

    The code doesn't include details on how to create an index list, how to determine rhe return type once the call is sorted out, or how to deal with rvalue arguments...