unpacking a tuple to call a matching function pointer
The C++17 solution is simply to use std::apply
:
auto f = [](int a, double b, std::string c) { std::cout<<a<<" "<<b<<" "<<c<< std::endl; };
auto params = std::make_tuple(1,2.0,"Hello");
std::apply(f, params);
Just felt that should be stated once in an answer in this thread (after it already appeared in one of the comments).
The basic C++14 solution is still missing in this thread. EDIT: No, it's actually there in the answer of Walter.
This function is given:
void f(int a, double b, void* c)
{
std::cout << a << ":" << b << ":" << c << std::endl;
}
Call it with the following snippet:
template<typename Function, typename Tuple, size_t ... I>
auto call(Function f, Tuple t, std::index_sequence<I ...>)
{
return f(std::get<I>(t) ...);
}
template<typename Function, typename Tuple>
auto call(Function f, Tuple t)
{
static constexpr auto size = std::tuple_size<Tuple>::value;
return call(f, t, std::make_index_sequence<size>{});
}
Example:
int main()
{
std::tuple<int, double, int*> t;
//or std::array<int, 3> t;
//or std::pair<int, double> t;
call(f, t);
}
DEMO
Unpacking arguments from tuples
I think that @Xeo's comment summed it up well. From 14.5.3 of the C++11 standard:
A pack expansion consists of a pattern and an ellipsis, the
instantiation of which produces zero or more instantiations of the
pattern in a list.
In your case, by the time you finish with the recursive template instantiation and end up in the partial specialization, you have
f(std::get<N>(std::forward<Tuple>(t))...);
...where N
is parameter pack of four int
s (0
, 1
, 2
, and 3
). From the standardese above, the pattern here is
std::get<N>(std::forward<Tuple>(t))
The application of the ...
ellipsis to the above pattern causes it to be expanded into four instantiations in list form, i.e.
f(std::get<0>(t), std::get<1>(t), std::get<2>(t), std::get<3>(t));
Unpacking a range of tuples into n-ary function
It sounds like what you actually need is a function adaptor that explodes tuple arguments. Something like this (LIVE):
#include <type_traits>
#include <utility>
#include <range/v3/core.hpp>
#include <range/v3/utility/semiregular.hpp>
#include <range/v3/utility/tuple_algorithm.hpp>
template<class F>
struct decomposed_fn
{
private:
CONCEPT_ASSERT(ranges::CopyConstructible<F>());
ranges::semiregular_t<F> f_;
template<class FF>
struct caller
{
FF &f_;
template<class... Args>
RANGES_CXX14_CONSTEXPR auto operator()(Args &&...args)
RANGES_DECLTYPE_AUTO_RETURN_NOEXCEPT
(
ranges::invoke(f_, std::forward<Args>(args)...)
)
};
public:
decomposed_fn() = default;
RANGES_CXX14_CONSTEXPR explicit decomposed_fn(F f)
noexcept(std::is_nothrow_move_constructible<F>::value)
: f_(std::move(f))
{}
template<class T>
RANGES_CXX14_CONSTEXPR auto operator()(T &&t)
RANGES_DECLTYPE_AUTO_RETURN_NOEXCEPT
(
ranges::tuple_apply(caller<F>{f_}, std::forward<T>(t))
)
template<class T>
RANGES_CXX14_CONSTEXPR auto operator()(T &&t) const
RANGES_DECLTYPE_AUTO_RETURN_NOEXCEPT
(
ranges::tuple_apply(caller<F const>{f_}, std::forward<T>(t))
)
};
template<class F,
CONCEPT_REQUIRES_(ranges::CopyConstructible<std::decay_t<F>>())>
RANGES_CXX14_CONSTEXPR auto decomposed(F &&f)
RANGES_DECLTYPE_AUTO_RETURN_NOEXCEPT
(
decomposed_fn<std::decay_t<F>>(std::forward<F>(f))
)
with which you could formulate your range as:
auto chars = view::zip(r1, r2)
| view::transform(decomposed([](int, char x) { return x; }));
Variadic template returning a N-tuple based on an unknown number of arguments
That's heavy pseudocode, I'll answer with heavy pseudocode:
template<typename ... Ts>
constexpr auto fill_and_gen_objects(Ts* ... os)
{
bool some_status = true; //whatever
return std::make_tuple(some_status, gen_object(os) ...);
}
Ok, actually it even compiles, see here
EDIT: downgraded to C++14 ... that's what you've tagged.
Same for C++17 using CTAD
template<typename ... Ts>
constexpr auto fill_and_gen_objects(Ts* ... os)
{
bool some_status = true; //whatever
return std::tuple{some_status, gen_object(os) ...};
}
Same for C++20 using abbreviated function template syntax
constexpr auto fill_and_gen_objects(auto* ... os)
{
bool some_status = true; //whatever
return std::tuple{some_status, gen_object(os) ...};
}
C++20 with indices by using integer sequence (untested):
constexpr auto fill_and_gen_objects(auto* ... os)
{
bool some_status = true; //whatever
return []<int ... I>(std::index_sequence<I...>, auto tup){ return std::tuple{some_status, gen_object(std::get<I>(tup)) ...};}
(std::make_index_sequence<sizeof...(os)>{}, std::tuple{os...})
}
Furthermore, here is the C++27 solution:
void do_my_fckng_work() { bool asap = true; }
Related Topics
Store Hex Value as String (Arduino Project)
C++11 Std::To_String(Double) - No Trailing Zeros
Check If Element Found in Array C++
How to Install (V142) Build Tools in Visual Studio
Why Is "Using Namespace Std;" Considered Bad Practice
Escape Sequence \F - Form Feed - What Exactly Is It
How to Determine Opencv Version
How to Remove an Arbitrary Element from a Standard Heap in C++
Define Preprocessor Macro Through Cmake
What Are the Rules About Using an Underscore in a C++ Identifier
Print Heart Shape With Words Inside
Difference Between Function Overloading and Template Function Which Is More Appropriate
What Should Main() Return in C and C++
How to Split an Int into Its Digits
C++ Reading CSV File and Assigning Values to Array