3

Is there any way in c++11/14 to write variadic template function like this:

template <typename ReturnType, typename Args...>
std::function<ReturnType()> bindArgumentsFromTuple
                                  (std::function<ReturnType(Args... args)> f,
                                  const std::tuple<Args...>& t)

that binds elements of tuple t to function f as arguments (such that the number of elements and its types are identical in function arguments and tuple)?

Example of usage:

void dummy_print(int i, double d)
{
    std::cout << i << "," << d << '\n';
}
void dummy_print2(int i, double d, std::string& s)
{
    std::cout << i << "," << d <<  "," << s << '\n';
}

int main() {
    std::tuple<int,double> t(77,1.1);
    std::tuple<int,double,std::string> t2(1,2.0,"aaa");
    auto f1 = bindArgumentsFromTuple(dummy_print, t);
    f1();
    auto f2 = bindArgumentsFromTuple(dummy_print2, t2);
    f2();

    return 0;
}

2 Answers 2

3
template <typename F, typename T, std::size_t... indices>
auto bindTuple(F&& f, T&& t, std::index_sequence<indices...>) {
    return std::bind(std::forward<F>(f), std::get<indices>(std::forward<T>(t))...);
}

template <typename F, typename T>
auto bindTuple(F&& f, T&& t) {
    return bindTuple(std::forward<F>(f), std::forward<T>(t),
                   std::make_index_sequence<std::tuple_size<std::decay_t<T>>{}>{});
}

The above will support anything tuple-esque, i.e. std::array, std::tuple, etc., while regarding placeholder arguments. Demo.

Sign up to request clarification or add additional context in comments.

6 Comments

Thank you! It is my one more knowledge gap in c++: std::index_sequence :)
In the first overload wouldn't you be forwarding t (potentially moving it) multiple times?
@0x499602D2 I'm forwarding it so std::get can forward the tuple's elements accordingly, avoiding copies whenever possible
With STL's usual caveat about bind doing extra magic that may or may not be desirable.
@T.C. You mean INVOKE?
|
1

With std::index_sequence, you may do something like:

template <typename ReturnType, typename ...Args, std::size_t ... Is>
std::function<ReturnType()>
bindArgumentsFromTuple_impl(std::function<ReturnType(Args...)> f,
                       const std::tuple<Args...>& t, std::index_sequence<Is...>)
{
    return [=]() { return f(std::get<Is>(t)...);};
}

template <typename ReturnType, typename ...Args>
std::function<ReturnType()>
bindArgumentsFromTuple(std::function<ReturnType(Args...)> f,
                       const std::tuple<Args...>& t)
{
    return bindArgumentsFromTuple_impl(f, t, std::index_sequence_for<Args...>{});
}

Live Demo

5 Comments

std::function? Seriously?
I kept OP's signature, but your are right, your way is better.
The OP accepts strings with non-const references; I doubt he knows what's best for him :-)
Thank you! As I wrote to @Colombo, it is my another knowledge gap in c++: std::index_sequence :)
@attuda: You can't accept several answers, but you can up vote several answers.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.