0

Currently, I would use the following code below that mainly uses tuples to pass the first N variadic template arguments to a function. I was wondering if there would be a more memory-efficient or just better/easier way to replicate the following:

template<typename T, T... ints, class...DTs>
auto reduce_tuple(std::integer_sequence<T, ints...> int_seq, std::tuple<DTs&&...>&& t){
    return std::forward_as_tuple((std::move(std::get<ints>(t)))...);
}

template<class UnaryFunction, class... Types>
auto invoke_tuple_result(UnaryFunction&& unary, std::tuple<Types&&...> &&T){
    return std::invoke_result_t<UnaryFunction, Types...>();
}

//in this example, N represents the amount of arguments in the lambda function
// a good way to deduce how many arguments are in a lambda function can be found at https://stackoverflow.com/questions/54389831/count-the-number-of-arguments-in-a-lambda
// but for this example I am just going to use N
//I want for example the first argument to be 1, and then I want to use the first N elements from the args argument and use that as the rest of the arguments
//currently I accomplish this through tupples
template<std::size_t N, template UnaryFunction, template... Args>
auto invoke_variadic_template(UnaryFunction&& unary, Args&&... args){
    bool condition = true; //this may be a condition that is reduced from of 'args' I am, for simplicity, setting this to true
    if(condition){
        std::tuple<Args&&...> elements(std::forward<DTs>(args)...);
        auto t = reduce_tuple(std::make_index_sequence<N_size-1>{}, std::move(elements));
        int val = 1;
        std::tuple<int&&> n_val = std::forward_as_tuple(std::forward<int>(val));
        auto a = std::tuple_cat(std::move(n_val), std::move(t));
        return std::apply(unary, std::move(a));
    }
    int fail_val = 20;
    std::tuple<int&&> f_val = std::forward_as_tuple(std::forward<int>(fail_val));
    auto a = std::tuple_cat(std::move(f_val), std::move(t));
    return invoke_tuple_result(std::forward<UnaryFunction>(unary, std::move(a)), 
}

I was wondering if there was a more straight-forward way to do this that didn't rely on tuples. Or would something along these lines be the really only way to do this?

Sam Moldenha
  • 463
  • 2
  • 11
  • Unclear what `condition`/`val`/`fail_val` has to do with the asked question... – Jarod42 Sep 02 '23 at 06:18
  • `std::apply([&](auto&&...args){ return unary(1, args...) }, t);` seems simpler than `std::tuple_cat` usage. – Jarod42 Sep 02 '23 at 06:22
  • I have the feeling you are overcomplicating. Why not let your function accept two variadic structs? What is the client syntax you want to achieve and how much worse do you think `f(1,2,3.0,4.0)` is going to be than `f({1,2},{3.0,4.0})`? (The second one is I think much more explicit and maintainable) – Pepijn Kramer Sep 02 '23 at 06:34

0 Answers0