Convert std::tuple to std::array C++11 - c++

If I have std::tuple<double, double, double> (where the type is homogeneous), is there a stock function or constructor to convert to std::array<double>?
Edit:: I was able to get it working with recursive template code (my draft answer posted below). Is this the best way to handle this? It seems like there would be a stock function for this... Or if you have improvements to my answer, I'd appreciate it. I'll leave the question unanswered (after all, I want a good way, not just a workable way), and would prefer to select someone else's [hopefully better] answer.
Thanks for your advice.

Converting a tuple to an array without making use of recursion, including use of perfect-forwarding (useful for move-only types):
#include <iostream>
#include <tuple>
#include <array>
template<int... Indices>
struct indices {
using next = indices<Indices..., sizeof...(Indices)>;
};
template<int Size>
struct build_indices {
using type = typename build_indices<Size - 1>::type::next;
};
template<>
struct build_indices<0> {
using type = indices<>;
};
template<typename T>
using Bare = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
template<typename Tuple>
constexpr
typename build_indices<std::tuple_size<Bare<Tuple>>::value>::type
make_indices()
{ return {}; }
template<typename Tuple, int... Indices>
std::array<
typename std::tuple_element<0, Bare<Tuple>>::type,
std::tuple_size<Bare<Tuple>>::value
>
to_array(Tuple&& tuple, indices<Indices...>)
{
using std::get;
return {{ get<Indices>(std::forward<Tuple>(tuple))... }};
}
template<typename Tuple>
auto to_array(Tuple&& tuple)
-> decltype( to_array(std::declval<Tuple>(), make_indices<Tuple>()) )
{
return to_array(std::forward<Tuple>(tuple), make_indices<Tuple>());
}
int main() {
std::tuple<double, double, double> tup(1.5, 2.5, 4.5);
auto arr = to_array(tup);
for (double x : arr)
std::cout << x << " ";
std::cout << std::endl;
return 0;
}

The C++17 solution is a short one:
template<typename tuple_t>
constexpr auto get_array_from_tuple(tuple_t&& tuple)
{
constexpr auto get_array = [](auto&& ... x){ return std::array{std::forward<decltype(x)>(x) ... }; };
return std::apply(get_array, std::forward<tuple_t>(tuple));
}
Use it as
auto tup = std::make_tuple(1.0,2.0,3.0);
auto arr = get_array_from_tuple(tup);
EDIT: forgot to sprinkle constexpr anywhere :-)

You can do it non-recursively:
#include <array>
#include <tuple>
#include <redi/index_tuple.h> // see below
template<typename T, typename... U>
using Array = std::array<T, 1+sizeof...(U)>;
template<typename T, typename... U, unsigned... I>
inline Array<T, U...>
tuple_to_array2(const std::tuple<T, U...>& t, redi::index_tuple<I...>)
{
return Array<T, U...>{ std::get<I>(t)... };
}
template<typename T, typename... U>
inline Array<T, U...>
tuple_to_array(const std::tuple<T, U...>& t)
{
using IndexTuple = typename redi::make_index_tuple<1+sizeof...(U)>::type;
return tuple_to_array2(t, IndexTuple());
}
See https://gitlab.com/redistd/redistd/blob/master/include/redi/index_tuple.h for my implementation of index_tuple, something like that is useful for working with tuples and similar variadic templates. A similar utility was standardised as std::index_sequence in C++14 (see index_seq.h for a standalone C++11 implementation).

I would return the array instead of populating it by reference, so that auto can be used to make the callsite cleaner:
template<typename First, typename... Rem>
std::array<First, 1+sizeof...(Rem)>
fill_array_from_tuple(const std::tuple<First, Rem...>& t) {
std::array<First, 1+sizeof...(Rem)> arr;
ArrayFiller<First, decltype(t), 1+sizeof...(Rem)>::fill_array_from_tuple(t, arr);
return arr;
}
// ...
std::tuple<double, double, double> tup(0.1, 0.2, 0.3);
auto arr = fill_array_from_tuple(tup);
Realistically, NRVO will eliminate most performance concerns.

#include <iostream>
#include <tuple>
#include <array>
template<class First, class Tuple, std::size_t N, std::size_t K = N>
struct ArrayFiller {
static void fill_array_from_tuple(const Tuple& t, std::array<First, N> & arr) {
ArrayFiller<First, Tuple, N, K-1>::fill_array_from_tuple(t, arr);
arr[K-1] = std::get<K-1>(t);
}
};
template<class First, class Tuple, std::size_t N>
struct ArrayFiller<First, Tuple, N, 1> {
static void fill_array_from_tuple( const Tuple& t, std::array<First, N> & arr) {
arr[0] = std::get<0>(t);
}
};
template<typename First, typename... Rem>
void fill_array_from_tuple(const std::tuple<First, Rem...>& t, std::array<First, 1+sizeof...(Rem)> & arr) {
ArrayFiller<First, decltype(t), 1+sizeof...(Rem)>::fill_array_from_tuple(t, arr);
}
int main() {
std::tuple<double, double, double> tup(0.1, 0.2, 0.3);
std::array<double, 3> arr;
fill_array_from_tuple(tup, arr);
for (double x : arr)
std::cout << x << " ";
return 0;
}

Even if title says C++11 I think C++14 solution is worth sharing (since everyone searching for problem will come up here anyway). This one can be used in compile time (constexpr proper) and much shorter than other solutions.
#include <array>
#include <tuple>
#include <utility>
#include <iostream>
// Convert tuple into a array implementation
template<typename T, std::size_t N, typename Tuple, std::size_t... I>
constexpr decltype(auto) t2a_impl(const Tuple& a, std::index_sequence<I...>)
{
return std::array<T,N>{std::get<I>(a)...};
}
// Convert tuple into a array
template<typename Head, typename... T>
constexpr decltype(auto) t2a(const std::tuple<Head, T...>& a)
{
using Tuple = std::tuple<Head, T...>;
constexpr auto N = sizeof...(T) + 1;
return t2a_impl<Head, N, Tuple>(a, std::make_index_sequence<N>());
}
int main()
{
constexpr auto tuple = std::make_tuple(-1.3,2.1,3.5);
constexpr auto array = t2a(tuple);
static_assert(array.size() == 3, "err");
for(auto k : array)
std::cout << k << ' ';
return 0;
}
Example

In C++14 you can do this to generate an array:
auto arr = apply([](auto... n){return std::array<double, sizeof...(n)>{n...};}, tup);
Full code:
#include<experimental/tuple> // apply
#include<cassert>
//using std::experimental::apply; c++14 + experimental
using std::apply; // c++17
template<class T, class Tuple>
auto to_array(Tuple&& t){
return apply([](auto... n){return std::array<T, sizeof...(n)>{n...};}, t); // c++14 + exp
}
int main(){
std::tuple<int, int, int> t{2, 3, 4};
auto a = apply([](auto... n){return std::array<int, 3>{n...};}, t); // c++14 + exp
assert( a[1] == 3 );
auto a2 = apply([](auto... n){return std::array<int, sizeof...(n)>{n...};}, t); // c++14 + exp
assert( a2[1] == 3 );
auto a3 = apply([](auto... n){return std::array{n...};}, t); // c++17
assert( a3[1] == 3 );
auto a4 = to_array<int>(t);
assert( a4[1] == 3 );
}
Note that the subtle problem is what to do when all types in the source tuple are not the same, should it fail to compile? use implicit conversion rules? use explicit conversion rules?

Related

Can't get tuple member by its index in a loop [duplicate]

How can I iterate over a tuple (using C++11)? I tried the following:
for(int i=0; i<std::tuple_size<T...>::value; ++i)
std::get<i>(my_tuple).do_sth();
but this doesn't work:
Error 1: sorry, unimplemented: cannot expand ‘Listener ...’ into a fixed-length argument list.
Error 2: i cannot appear in a constant expression.
So, how do I correctly iterate over the elements of a tuple?
I have an answer based on Iterating over a Tuple:
#include <tuple>
#include <utility>
#include <iostream>
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type
print(std::tuple<Tp...>& t)
{ }
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I < sizeof...(Tp), void>::type
print(std::tuple<Tp...>& t)
{
std::cout << std::get<I>(t) << std::endl;
print<I + 1, Tp...>(t);
}
int
main()
{
typedef std::tuple<int, float, double> T;
T t = std::make_tuple(2, 3.14159F, 2345.678);
print(t);
}
The usual idea is to use compile time recursion. In fact, this idea is used to make a printf that is type safe as noted in the original tuple papers.
This can be easily generalized into a for_each for tuples:
#include <tuple>
#include <utility>
template<std::size_t I = 0, typename FuncT, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type
for_each(std::tuple<Tp...> &, FuncT) // Unused arguments are given no names.
{ }
template<std::size_t I = 0, typename FuncT, typename... Tp>
inline typename std::enable_if<I < sizeof...(Tp), void>::type
for_each(std::tuple<Tp...>& t, FuncT f)
{
f(std::get<I>(t));
for_each<I + 1, FuncT, Tp...>(t, f);
}
Though this then requires some effort to have FuncT represent something with the appropriate overloads for every type the tuple might contain. This works best if you know all the tuple elements will share a common base class or something similar.
In C++17, you can use std::apply with fold expression:
std::apply([](auto&&... args) {((/* args.dosomething() */), ...);}, the_tuple);
A complete example for printing a tuple:
#include <tuple>
#include <iostream>
int main()
{
std::tuple t{42, 'a', 4.2}; // Another C++17 feature: class template argument deduction
std::apply([](auto&&... args) {((std::cout << args << '\n'), ...);}, t);
}
[Online Example on Coliru]
This solution solves the issue of evaluation order in M. Alaggan's answer.
C++ is introducing expansion statements for this purpose. They were originally on track for C++20 but narrowly missed the cut due to a lack of time for language wording review (see here and here).
The currently agreed syntax (see the links above) is:
{
auto tup = std::make_tuple(0, 'a', 3.14);
template for (auto elem : tup)
std::cout << elem << std::endl;
}
Boost.Fusion is a possibility:
Untested example:
struct DoSomething
{
template<typename T>
void operator()(T& t) const
{
t.do_sth();
}
};
tuple<....> t = ...;
boost::fusion::for_each(t, DoSomething());
In C++17 you can do this:
std::apply([](auto ...x){std::make_tuple(x.do_something()...);} , the_tuple);
This already works in Clang++ 3.9, using std::experimental::apply.
A more simple, intuitive and compiler-friendly way of doing this in C++17, using if constexpr:
// prints every element of a tuple
template<size_t I = 0, typename... Tp>
void print(std::tuple<Tp...>& t) {
std::cout << std::get<I>(t) << " ";
// do things
if constexpr(I+1 != sizeof...(Tp))
print<I+1>(t);
}
This is compile-time recursion, similar to the one presented by #emsr. But this doesn't use SFINAE so (I think) it is more compiler-friendly.
Use Boost.Hana and generic lambdas:
#include <tuple>
#include <iostream>
#include <boost/hana.hpp>
#include <boost/hana/ext/std/tuple.hpp>
struct Foo1 {
int foo() const { return 42; }
};
struct Foo2 {
int bar = 0;
int foo() { bar = 24; return bar; }
};
int main() {
using namespace std;
using boost::hana::for_each;
Foo1 foo1;
Foo2 foo2;
for_each(tie(foo1, foo2), [](auto &foo) {
cout << foo.foo() << endl;
});
cout << "foo2.bar after mutation: " << foo2.bar << endl;
}
http://coliru.stacked-crooked.com/a/27b3691f55caf271
Here's an easy C++17 way of iterating over tuple items with just standard library:
#include <tuple> // std::tuple
#include <functional> // std::invoke
template <
size_t Index = 0, // start iteration at 0 index
typename TTuple, // the tuple type
size_t Size =
std::tuple_size_v<
std::remove_reference_t<TTuple>>, // tuple size
typename TCallable, // the callable to be invoked for each tuple item
typename... TArgs // other arguments to be passed to the callable
>
void for_each(TTuple&& tuple, TCallable&& callable, TArgs&&... args)
{
if constexpr (Index < Size)
{
std::invoke(callable, args..., std::get<Index>(tuple));
if constexpr (Index + 1 < Size)
for_each<Index + 1>(
std::forward<TTuple>(tuple),
std::forward<TCallable>(callable),
std::forward<TArgs>(args)...);
}
}
Example:
#include <iostream>
int main()
{
std::tuple<int, char> items{1, 'a'};
for_each(items, [](const auto& item) {
std::cout << item << "\n";
});
}
Output:
1
a
This can be extended to conditionally break the loop in case the callable returns a value (but still work with callables that do not return a bool assignable value, e.g. void):
#include <tuple> // std::tuple
#include <functional> // std::invoke
template <
size_t Index = 0, // start iteration at 0 index
typename TTuple, // the tuple type
size_t Size =
std::tuple_size_v<
std::remove_reference_t<TTuple>>, // tuple size
typename TCallable, // the callable to bo invoked for each tuple item
typename... TArgs // other arguments to be passed to the callable
>
void for_each(TTuple&& tuple, TCallable&& callable, TArgs&&... args)
{
if constexpr (Index < Size)
{
if constexpr (std::is_assignable_v<bool&, std::invoke_result_t<TCallable&&, TArgs&&..., decltype(std::get<Index>(tuple))>>)
{
if (!std::invoke(callable, args..., std::get<Index>(tuple)))
return;
}
else
{
std::invoke(callable, args..., std::get<Index>(tuple));
}
if constexpr (Index + 1 < Size)
for_each<Index + 1>(
std::forward<TTuple>(tuple),
std::forward<TCallable>(callable),
std::forward<TArgs>(args)...);
}
}
Example:
#include <iostream>
int main()
{
std::tuple<int, char> items{ 1, 'a' };
for_each(items, [](const auto& item) {
std::cout << item << "\n";
});
std::cout << "---\n";
for_each(items, [](const auto& item) {
std::cout << item << "\n";
return false;
});
}
Output:
1
a
---
1
You need to use template metaprogramming, here shown with Boost.Tuple:
#include <boost/tuple/tuple.hpp>
#include <iostream>
template <typename T_Tuple, size_t size>
struct print_tuple_helper {
static std::ostream & print( std::ostream & s, const T_Tuple & t ) {
return print_tuple_helper<T_Tuple,size-1>::print( s, t ) << boost::get<size-1>( t );
}
};
template <typename T_Tuple>
struct print_tuple_helper<T_Tuple,0> {
static std::ostream & print( std::ostream & s, const T_Tuple & ) {
return s;
}
};
template <typename T_Tuple>
std::ostream & print_tuple( std::ostream & s, const T_Tuple & t ) {
return print_tuple_helper<T_Tuple,boost::tuples::length<T_Tuple>::value>::print( s, t );
}
int main() {
const boost::tuple<int,char,float,char,double> t( 0, ' ', 2.5f, '\n', 3.1416 );
print_tuple( std::cout, t );
return 0;
}
In C++0x, you can write print_tuple() as a variadic template function instead.
First define some index helpers:
template <size_t ...I>
struct index_sequence {};
template <size_t N, size_t ...I>
struct make_index_sequence : public make_index_sequence<N - 1, N - 1, I...> {};
template <size_t ...I>
struct make_index_sequence<0, I...> : public index_sequence<I...> {};
With your function you would like to apply on each tuple element:
template <typename T>
/* ... */ foo(T t) { /* ... */ }
you can write:
template<typename ...T, size_t ...I>
/* ... */ do_foo_helper(std::tuple<T...> &ts, index_sequence<I...>) {
std::tie(foo(std::get<I>(ts)) ...);
}
template <typename ...T>
/* ... */ do_foo(std::tuple<T...> &ts) {
return do_foo_helper(ts, make_index_sequence<sizeof...(T)>());
}
Or if foo returns void, use
std::tie((foo(std::get<I>(ts)), 1) ... );
Note: On C++14 make_index_sequence is already defined (http://en.cppreference.com/w/cpp/utility/integer_sequence).
If you do need a left-to-right evaluation order, consider something like this:
template <typename T, typename ...R>
void do_foo_iter(T t, R ...r) {
foo(t);
do_foo(r...);
}
void do_foo_iter() {}
template<typename ...T, size_t ...I>
void do_foo_helper(std::tuple<T...> &ts, index_sequence<I...>) {
do_foo_iter(std::get<I>(ts) ...);
}
template <typename ...T>
void do_foo(std::tuple<T...> &ts) {
do_foo_helper(ts, make_index_sequence<sizeof...(T)>());
}
If you want to use std::tuple and you have C++ compiler which supports variadic templates, try code bellow (tested with g++4.5). This should be the answer to your question.
#include <tuple>
// ------------- UTILITY---------------
template<int...> struct index_tuple{};
template<int I, typename IndexTuple, typename... Types>
struct make_indexes_impl;
template<int I, int... Indexes, typename T, typename ... Types>
struct make_indexes_impl<I, index_tuple<Indexes...>, T, Types...>
{
typedef typename make_indexes_impl<I + 1, index_tuple<Indexes..., I>, Types...>::type type;
};
template<int I, int... Indexes>
struct make_indexes_impl<I, index_tuple<Indexes...> >
{
typedef index_tuple<Indexes...> type;
};
template<typename ... Types>
struct make_indexes : make_indexes_impl<0, index_tuple<>, Types...>
{};
// ----------- FOR EACH -----------------
template<typename Func, typename Last>
void for_each_impl(Func&& f, Last&& last)
{
f(last);
}
template<typename Func, typename First, typename ... Rest>
void for_each_impl(Func&& f, First&& first, Rest&&...rest)
{
f(first);
for_each_impl( std::forward<Func>(f), rest...);
}
template<typename Func, int ... Indexes, typename ... Args>
void for_each_helper( Func&& f, index_tuple<Indexes...>, std::tuple<Args...>&& tup)
{
for_each_impl( std::forward<Func>(f), std::forward<Args>(std::get<Indexes>(tup))...);
}
template<typename Func, typename ... Args>
void for_each( std::tuple<Args...>& tup, Func&& f)
{
for_each_helper(std::forward<Func>(f),
typename make_indexes<Args...>::type(),
std::forward<std::tuple<Args...>>(tup) );
}
template<typename Func, typename ... Args>
void for_each( std::tuple<Args...>&& tup, Func&& f)
{
for_each_helper(std::forward<Func>(f),
typename make_indexes<Args...>::type(),
std::forward<std::tuple<Args...>>(tup) );
}
boost::fusion is another option, but it requires its own tuple type: boost::fusion::tuple. Lets better stick to the standard! Here is a test:
#include <iostream>
// ---------- FUNCTOR ----------
struct Functor
{
template<typename T>
void operator()(T& t) const { std::cout << t << std::endl; }
};
int main()
{
for_each( std::make_tuple(2, 0.6, 'c'), Functor() );
return 0;
}
the power of variadic templates!
In MSVC STL there's a _For_each_tuple_element function (not documented):
#include <tuple>
// ...
std::tuple<int, char, float> values{};
std::_For_each_tuple_element(values, [](auto&& value)
{
// process 'value'
});
Another option would be to implement iterators for tuples. This has the advantage that you can use a variety of algorithms provided by the standard library and range-based for loops. An elegant approach to this is explained here https://foonathan.net/2017/03/tuple-iterator/. The basic idea is to turn tuples into a range with begin() and end() methods to provide iterators. The iterator itself returns a std::variant<...> which can then be visited using std::visit.
Here some examples:
auto t = std::tuple{ 1, 2.f, 3.0 };
auto r = to_range(t);
for(auto v : r)
{
std::visit(unwrap([](auto& x)
{
x = 1;
}), v);
}
std::for_each(begin(r), end(r), [](auto v)
{
std::visit(unwrap([](auto& x)
{
x = 0;
}), v);
});
std::accumulate(begin(r), end(r), 0.0, [](auto acc, auto v)
{
return acc + std::visit(unwrap([](auto& x)
{
return static_cast<double>(x);
}), v);
});
std::for_each(begin(r), end(r), [](auto v)
{
std::visit(unwrap([](const auto& x)
{
std::cout << x << std::endl;
}), v);
});
std::for_each(begin(r), end(r), [](auto v)
{
std::visit(overload(
[](int x) { std::cout << "int" << std::endl; },
[](float x) { std::cout << "float" << std::endl; },
[](double x) { std::cout << "double" << std::endl; }), v);
});
My implementation (which is heavily based on the explanations in the link above):
#ifndef TUPLE_RANGE_H
#define TUPLE_RANGE_H
#include <utility>
#include <functional>
#include <variant>
#include <type_traits>
template<typename Accessor>
class tuple_iterator
{
public:
tuple_iterator(Accessor acc, const int idx)
: acc_(acc), index_(idx)
{
}
tuple_iterator operator++()
{
++index_;
return *this;
}
template<typename T>
bool operator ==(tuple_iterator<T> other)
{
return index_ == other.index();
}
template<typename T>
bool operator !=(tuple_iterator<T> other)
{
return index_ != other.index();
}
auto operator*() { return std::invoke(acc_, index_); }
[[nodiscard]] int index() const { return index_; }
private:
const Accessor acc_;
int index_;
};
template<bool IsConst, typename...Ts>
struct tuple_access
{
using tuple_type = std::tuple<Ts...>;
using tuple_ref = std::conditional_t<IsConst, const tuple_type&, tuple_type&>;
template<typename T>
using element_ref = std::conditional_t<IsConst,
std::reference_wrapper<const T>,
std::reference_wrapper<T>>;
using variant_type = std::variant<element_ref<Ts>...>;
using function_type = variant_type(*)(tuple_ref);
using table_type = std::array<function_type, sizeof...(Ts)>;
private:
template<size_t Index>
static constexpr function_type create_accessor()
{
return { [](tuple_ref t) -> variant_type
{
if constexpr (IsConst)
return std::cref(std::get<Index>(t));
else
return std::ref(std::get<Index>(t));
} };
}
template<size_t...Is>
static constexpr table_type create_table(std::index_sequence<Is...>)
{
return { create_accessor<Is>()... };
}
public:
static constexpr auto table = create_table(std::make_index_sequence<sizeof...(Ts)>{});
};
template<bool IsConst, typename...Ts>
class tuple_range
{
public:
using tuple_access_type = tuple_access<IsConst, Ts...>;
using tuple_ref = typename tuple_access_type::tuple_ref;
static constexpr auto tuple_size = sizeof...(Ts);
explicit tuple_range(tuple_ref tuple)
: tuple_(tuple)
{
}
[[nodiscard]] auto begin() const
{
return tuple_iterator{ create_accessor(), 0 };
}
[[nodiscard]] auto end() const
{
return tuple_iterator{ create_accessor(), tuple_size };
}
private:
tuple_ref tuple_;
auto create_accessor() const
{
return [this](int idx)
{
return std::invoke(tuple_access_type::table[idx], tuple_);
};
}
};
template<bool IsConst, typename...Ts>
auto begin(const tuple_range<IsConst, Ts...>& r)
{
return r.begin();
}
template<bool IsConst, typename...Ts>
auto end(const tuple_range<IsConst, Ts...>& r)
{
return r.end();
}
template <class ... Fs>
struct overload : Fs... {
explicit overload(Fs&&... fs) : Fs{ fs }... {}
using Fs::operator()...;
template<class T>
auto operator()(std::reference_wrapper<T> ref)
{
return (*this)(ref.get());
}
template<class T>
auto operator()(std::reference_wrapper<const T> ref)
{
return (*this)(ref.get());
}
};
template <class F>
struct unwrap : overload<F>
{
explicit unwrap(F&& f) : overload<F>{ std::forward<F>(f) } {}
using overload<F>::operator();
};
template<typename...Ts>
auto to_range(std::tuple<Ts...>& t)
{
return tuple_range<false, Ts...>{t};
}
template<typename...Ts>
auto to_range(const std::tuple<Ts...>& t)
{
return tuple_range<true, Ts...>{t};
}
#endif
Read-only access is also supported by passing a const std::tuple<>& to to_range().
Others have mentioned some well-designed third-party libraries that you may turn to. However, if you are using C++ without those third-party libraries, the following code may help.
namespace detail {
template <class Tuple, std::size_t I, class = void>
struct for_each_in_tuple_helper {
template <class UnaryFunction>
static void apply(Tuple&& tp, UnaryFunction& f) {
f(std::get<I>(std::forward<Tuple>(tp)));
for_each_in_tuple_helper<Tuple, I + 1u>::apply(std::forward<Tuple>(tp), f);
}
};
template <class Tuple, std::size_t I>
struct for_each_in_tuple_helper<Tuple, I, typename std::enable_if<
I == std::tuple_size<typename std::decay<Tuple>::type>::value>::type> {
template <class UnaryFunction>
static void apply(Tuple&&, UnaryFunction&) {}
};
} // namespace detail
template <class Tuple, class UnaryFunction>
UnaryFunction for_each_in_tuple(Tuple&& tp, UnaryFunction f) {
detail::for_each_in_tuple_helper<Tuple, 0u>
::apply(std::forward<Tuple>(tp), f);
return std::move(f);
}
Note: The code compiles with any compiler supporing C++11, and it keeps consistency with design of the standard library:
The tuple need not be std::tuple, and instead may be anything that supports std::get and std::tuple_size; in particular, std::array and std::pair may be used;
The tuple may be a reference type or cv-qualified;
It has similar behavior as std::for_each, and returns the input UnaryFunction;
For C++14 (or laster version) users, typename std::enable_if<T>::type and typename std::decay<T>::type could be replaced with their simplified version, std::enable_if_t<T> and std::decay_t<T>;
For C++17 (or laster version) users, std::tuple_size<T>::value could be replaced with its simplified version, std::tuple_size_v<T>.
For C++20 (or laster version) users, the SFINAE feature could be implemented with the Concepts.
Using constexpr and if constexpr(C++17) this is fairly simple and straight forward:
template <std::size_t I = 0, typename ... Ts>
void print(std::tuple<Ts...> tup) {
if constexpr (I == sizeof...(Ts)) {
return;
} else {
std::cout << std::get<I>(tup) << ' ';
print<I+1>(tup);
}
}
I might have missed this train, but this will be here for future reference.
Here's my construct based on this answer and on this gist:
#include <tuple>
#include <utility>
template<std::size_t N>
struct tuple_functor
{
template<typename T, typename F>
static void run(std::size_t i, T&& t, F&& f)
{
const std::size_t I = (N - 1);
switch(i)
{
case I:
std::forward<F>(f)(std::get<I>(std::forward<T>(t)));
break;
default:
tuple_functor<I>::run(i, std::forward<T>(t), std::forward<F>(f));
}
}
};
template<>
struct tuple_functor<0>
{
template<typename T, typename F>
static void run(std::size_t, T, F){}
};
You then use it as follow:
template<typename... T>
void logger(std::string format, T... args) //behaves like C#'s String.Format()
{
auto tp = std::forward_as_tuple(args...);
auto fc = [](const auto& t){std::cout << t;};
/* ... */
std::size_t some_index = ...
tuple_functor<sizeof...(T)>::run(some_index, tp, fc);
/* ... */
}
There could be room for improvements.
As per OP's code, it would become this:
const std::size_t num = sizeof...(T);
auto my_tuple = std::forward_as_tuple(t...);
auto do_sth = [](const auto& elem){/* ... */};
for(int i = 0; i < num; ++i)
tuple_functor<num>::run(i, my_tuple, do_sth);
Of all the answers I've seen here, here and here, I liked #sigidagi's way of iterating best. Unfortunately, his answer is very verbose which in my opinion obscures the inherent clarity.
This is my version of his solution which is more concise and works with std::tuple, std::pair and std::array.
template<typename UnaryFunction>
void invoke_with_arg(UnaryFunction)
{}
/**
* Invoke the unary function with each of the arguments in turn.
*/
template<typename UnaryFunction, typename Arg0, typename... Args>
void invoke_with_arg(UnaryFunction f, Arg0&& a0, Args&&... as)
{
f(std::forward<Arg0>(a0));
invoke_with_arg(std::move(f), std::forward<Args>(as)...);
}
template<typename Tuple, typename UnaryFunction, std::size_t... Indices>
void for_each_helper(Tuple&& t, UnaryFunction f, std::index_sequence<Indices...>)
{
using std::get;
invoke_with_arg(std::move(f), get<Indices>(std::forward<Tuple>(t))...);
}
/**
* Invoke the unary function for each of the elements of the tuple.
*/
template<typename Tuple, typename UnaryFunction>
void for_each(Tuple&& t, UnaryFunction f)
{
using size = std::tuple_size<typename std::remove_reference<Tuple>::type>;
for_each_helper(
std::forward<Tuple>(t),
std::move(f),
std::make_index_sequence<size::value>()
);
}
Demo: coliru
C++14's std::make_index_sequence can be implemented for C++11.
Expanding on #Stypox answer, we can make their solution more generic (C++17 onward). By adding a callable function argument:
template<size_t I = 0, typename... Tp, typename F>
void for_each_apply(std::tuple<Tp...>& t, F &&f) {
f(std::get<I>(t));
if constexpr(I+1 != sizeof...(Tp)) {
for_each_apply<I+1>(t, std::forward<F>(f));
}
}
Then, we need a strategy to visit each type.
Let start with some helpers (first two taken from cppreference):
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
template<class ... Ts> struct variant_ref { using type = std::variant<std::reference_wrapper<Ts>...>; };
variant_ref is used to allow tuples' state to be modified.
Usage:
std::tuple<Foo, Bar, Foo> tuples;
for_each_apply(tuples,
[](variant_ref<Foo, Bar>::type &&v) {
std::visit(overloaded {
[](Foo &arg) { arg.foo(); },
[](Bar const &arg) { arg.bar(); },
}, v);
});
Result:
Foo0
Bar
Foo0
Foo1
Bar
Foo1
For completeness, here are my Bar & Foo:
struct Foo {
void foo() {std::cout << "Foo" << i++ << std::endl;}
int i = 0;
};
struct Bar {
void bar() const {std::cout << "Bar" << std::endl;}
};
I have stumbled on the same problem for iterating over a tuple of function objects, so here is one more solution:
#include <tuple>
#include <iostream>
// Function objects
class A
{
public:
inline void operator()() const { std::cout << "A\n"; };
};
class B
{
public:
inline void operator()() const { std::cout << "B\n"; };
};
class C
{
public:
inline void operator()() const { std::cout << "C\n"; };
};
class D
{
public:
inline void operator()() const { std::cout << "D\n"; };
};
// Call iterator using recursion.
template<typename Fobjects, int N = 0>
struct call_functors
{
static void apply(Fobjects const& funcs)
{
std::get<N>(funcs)();
// Choose either the stopper or descend further,
// depending if N + 1 < size of the tuple.
using caller = std::conditional_t
<
N + 1 < std::tuple_size_v<Fobjects>,
call_functors<Fobjects, N + 1>,
call_functors<Fobjects, -1>
>;
caller::apply(funcs);
}
};
// Stopper.
template<typename Fobjects>
struct call_functors<Fobjects, -1>
{
static void apply(Fobjects const& funcs)
{
}
};
// Call dispatch function.
template<typename Fobjects>
void call(Fobjects const& funcs)
{
call_functors<Fobjects>::apply(funcs);
};
using namespace std;
int main()
{
using Tuple = tuple<A,B,C,D>;
Tuple functors = {A{}, B{}, C{}, D{}};
call(functors);
return 0;
}
Output:
A
B
C
D
There're many great answers, but for some reason most of them don't consider returning the results of applying f to our tuple...
or did I overlook it? Anyway, here's yet another way you can do that:
Doing Foreach with style (debatable)
auto t = std::make_tuple(1, "two", 3.f);
t | foreach([](auto v){ std::cout << v << " "; });
And returning from that:
auto t = std::make_tuple(1, "two", 3.f);
auto sizes = t | foreach([](auto v) {
return sizeof(v);
});
sizes | foreach([](auto v) {
std::cout << v;
});
Implementation (pretty simple one)
Edit: it gets a little messier.
I won't include some metaprogramming boilerplate here, for it will definitely make things less readable and besides, I believe those have already been answered somewhere on stackoverflow.
In case you're feeling lazy, feel free to peek into my github repo for implementation of both
#include <utility>
// Optional includes, if you don't want to implement it by hand or google it
// you can find it in the repo (link below)
#include "typesystem/typelist.hpp"
// used to check if all return types are void,
// making it a special case
// (and, alas, not using constexpr-if
// for the sake of being compatible with C++14...)
template <bool Cond, typename T, typename F>
using select = typename std::conditional<Cond, T, F>::type;
template <typename F>
struct elementwise_apply {
F f;
};
template <typename F>
constexpr auto foreach(F && f) -> elementwise_apply<F> { return {std::forward<F>(f)}; }
template <typename R>
struct tuple_map {
template <typename F, typename T, size_t... Is>
static constexpr decltype(auto) impl(std::index_sequence<Is...>, F && f, T&& tuple) {
return R{ std::forward<F>(f)( std::get<Is>(tuple) )... };
}
};
template<>
struct tuple_map<void> {
template <typename F, typename T, size_t... Is>
static constexpr void impl(std::index_sequence<Is...>, F && f, T&& tuple) {
[[maybe_unused]] std::initializer_list<int> _ {((void)std::forward<F>(f)( std::get<Is>(tuple) ), 0)... };
}
};
template <typename F, typename... Ts>
constexpr decltype(auto) operator| (std::tuple<Ts...> & t, fmap<F> && op) {
constexpr bool all_void = core::Types<decltype( std::move(op).f(std::declval<Ts&>()) )...>.all( core::is_void );
using R = meta::select<all_void, void, std::tuple<decltype(std::move(op).f(std::declval<Ts&>()))...>>;
return tuple_map<R>::impl(std::make_index_sequence<sizeof...(Ts)>{}, std::move(op).f, t);
}
template <typename F, typename... Ts>
constexpr decltype(auto) operator| (std::tuple<Ts...> const& t, fmap<F> && op) {
constexpr bool all_void = check if all "decltype( std::move(op).f(std::declval<Ts>()) )..." types are void, since then it's a special case
// e.g. core::Types<decltype( std::move(op).f(std::declval<Ts>()) )...>.all( core::is_void );
using R = meta::select<all_void, void, std::tuple<decltype(std::move(op).f(std::declval<Ts const&>()))...>>;
return tuple_map<R>::impl(std::make_index_sequence<sizeof...(Ts)>{}, std::move(op).f, t);
}
template <typename F, typename... Ts>
constexpr decltype(auto) operator| (std::tuple<Ts...> && t, fmap<F> && op) {
constexpr bool all_void = core::Types<decltype( std::move(op).f(std::declval<Ts&&>()) )...>.all( core::is_void );
using R = meta::select<all_void, void, std::tuple<decltype(std::move(op).f(std::declval<Ts&&>()))...>>;
return tuple_map<R>::impl(std::make_index_sequence<sizeof...(Ts)>{}, std::move(op).f, std::move(t));
}
Yeah, that would be much nicer if we were to use C++17
This is also an example of std::moving object's members, for which I'll better refer to this nice brief article
P.S. If you're stuck checking if all "decltype( std::move(op).f(std::declval()) )..." types are void
you can find some metaprogramming library, or, if those libraries seem too hard to grasp (which some of them may be due to some crazy metaprogramming tricks), you know where to look
template <typename F, typename T>
static constexpr size_t
foreach_in_tuple(std::tuple<T> & tuple, F && do_, size_t index_ = 0)
{
do_(tuple, index_);
return index_;
}
template <typename F, typename T, typename U, typename... Types>
static constexpr size_t
foreach_in_tuple(std::tuple<T,U,Types...> & tuple, F && do_, size_t index_ = 0)
{
if(!do_(tuple, index_))
return index_;
auto & next_tuple = reinterpret_cast<std::tuple<U,Types...> &>(tuple);
return foreach_in_tuple(next_tuple, std::forward<F>(do_), index_+1);
}
int main()
{
using namespace std;
auto tup = make_tuple(1, 2.3f, 'G', "hello");
foreach_in_tuple(tup, [](auto & tuple, size_t i)
{
auto & value = std::get<0>(tuple);
std::cout << i << " " << value << std::endl;
// if(i >= 2) return false; // break;
return true; // continue
});
}
Here is a solution based on std::interger_sequence.
As I don't know if my_tuple is constructed from std::make_tuple<T>(T &&...) in your code. It's essential for how to construct std::integer_sequence in the solution below.
(1) if your already have a my_tuple outside your function(not using template<typename ...T>), You can use
[](auto my_tuple)
{
[&my_tuple]<typename N, N... n>(std::integer_sequence<N, n...> int_seq)
{
((std::cout << std::get<n>(my_tuple) << '\n'), ...);
}(std::make_index_sequence<std::tuple_size_v<decltype(my_tuple)>>{});
}(std::make_tuple());
(2) if your havn't constructed my_tuple in your function and want to handle your T ...arguments
[]<typename ...T>(T... args)
{
[&args...]<typename N, N... n>(std::integer_sequence<N, n...> int_seq)
{
((std::cout << std::get<n>(std::forward_as_tuple(args...)) << '\n'), ...);
}(std::index_sequence_for<T...>{});
}();
boost's tuple provides helper functions get_head() and get_tail() so your helper functions may look like this:
inline void call_do_sth(const null_type&) {};
template <class H, class T>
inline void call_do_sth(cons<H, T>& x) { x.get_head().do_sth(); call_do_sth(x.get_tail()); }
as described in here http://www.boost.org/doc/libs/1_34_0/libs/tuple/doc/tuple_advanced_interface.html
with std::tuple it should be similar.
Actually, unfortunately std::tuple does not seem to provide such interface, so methods suggested before should work, or you would need to switch to boost::tuple which has other benefits (like io operators already provided). Though there is downside of boost::tuple with gcc - it does not accept variadic templates yet, but that may be already fixed as I do not have latest version of boost installed on my machine.

Concatenating a sequence of std::arrays

Consider the following: (Wandbox)
#include <array>
#include <algorithm>
#include <iostream>
template<typename T, int N, int M>
auto concat(const std::array<T, N>& ar1, const std::array<T, M>& ar2)
{
std::array<T, N+M> result;
std::copy (ar1.cbegin(), ar1.cend(), result.begin());
std::copy (ar2.cbegin(), ar2.cend(), result.begin() + N);
return result;
}
int main()
{
std::array<int, 3> ar1 = {1, 2, 3};
std::array<int, 2> ar2 = {4, 5};
auto result = concat<int, 3, 2>(ar1, ar2);
for (auto& x : result)
std::cout << x << " ";
std::cout << std::endl;
return 0;
}
Given a sequence of std::array<T, length1>, std::array<T, length2>, ..., std::array<T, lengthK>, how can I generalize the above code and write a function which concatenates the sequence into an std::array<T, sum(lengths)>?
It would be nice if there is a way to write a reusable function which reduces a similar sequence of template classes using a given binary operation, e.g., use concat in the example above, rather than writing a special method (which would have to be re-written each time the binary op changes).
(IIUC, the relevant Standard Library algorithms (accumulate, reduce) only work in case the class of the result of the binary operation is always the same.)
Here is a simple C++17 solution via fold expressions:
#include <array>
#include <algorithm>
template <typename Type, std::size_t... sizes>
auto concatenate(const std::array<Type, sizes>&... arrays)
{
std::array<Type, (sizes + ...)> result;
std::size_t index{};
((std::copy_n(arrays.begin(), sizes, result.begin() + index), index += sizes), ...);
return result;
}
Example of using:
const std::array<int, 3> array1 = {{1, 2, 3}};
const std::array<int, 2> array2 = {{4, 5}};
const std::array<int, 4> array3 = {{6, 7, 8, 9}};
const auto result = concatenate(array1, array2, array3);
Live demo
You may do the following:
template <typename F, typename T, typename T2>
auto func(F f, T&& t, T2&& t2)
{
return f(std::forward<T>(t), std::forward<T2>(t2));
}
template <typename F, typename T, typename T2, typename ... Ts>
auto func(F f, T&& t, T2&& t2, Ts&&...args)
{
return func(f, f(std::forward<T>(t), std::forward<T2>(t2)), std::forward<Ts>(args)...);
}
With usage
struct concatenater
{
template<typename T, std::size_t N, std::size_t M>
auto operator()(const std::array<T, N>& ar1, const std::array<T, M>& ar2) const
{
std::array<T, N+M> result;
std::copy (ar1.cbegin(), ar1.cend(), result.begin());
std::copy (ar2.cbegin(), ar2.cend(), result.begin() + N);
return result;
}
};
and
auto result = func(concatenater{}, ar1, ar2, ar3, ar4);
C++14 Demo
C++11 Demo
Given a sequence of std::array<T, length1>, std::array<T, length2>, ..., std::array<T, lengthK>, how can I write a function which concatenates the sequence into an std::array<T, sum(lengths)>?
Here's a C++17 solution. It can very probably be shortened and improved, working on it.
template <std::size_t Last = 0, typename TF, typename TArray, typename... TRest>
constexpr auto with_acc_sizes(TF&& f, const TArray& array, const TRest&... rest)
{
f(array, std::integral_constant<std::size_t, Last>{});
if constexpr(sizeof...(TRest) != 0)
{
with_acc_sizes<Last + std::tuple_size_v<TArray>>(f, rest...);
}
}
template<typename T, std::size_t... Sizes>
constexpr auto concat(const std::array<T, Sizes>&... arrays)
{
std::array<T, (Sizes + ...)> result{};
with_acc_sizes([&](const auto& arr, auto offset)
{
std::copy(arr.begin(), arr.end(), result.begin() + offset);
}, arrays...);
return result;
}
Usage:
std::array<int, 3> ar1 = {1, 2, 3};
std::array<int, 2> ar2 = {4, 5};
std::array<int, 3> ar3 = {6, 7, 8};
auto result = concat(ar1, ar2, ar3);
live wandbox example
Works with both g++7 and clang++5.
My first line of reasoning would be to consider converting the array to a tuple of references (a tie), manipulate with tuple_cat and then perform whatever operation is necessary to build the final array (i.e. either move or copy - depending on the arguments originally passed in):
#include <array>
#include <iostream>
namespace detail {
template<class Array, std::size_t...Is>
auto array_as_tie(Array &a, std::index_sequence<Is...>) {
return std::tie(a[Is]...);
};
template<class T, class Tuple, std::size_t...Is>
auto copy_to_array(Tuple &t, std::index_sequence<Is...>) {
return std::array<T, sizeof...(Is)>
{
std::get<Is>(t)...
};
};
template<class T, class Tuple, std::size_t...Is>
auto move_to_array(Tuple &t, std::index_sequence<Is...>) {
return std::array<T, sizeof...(Is)>
{
std::move(std::get<Is>(t))...
};
};
}
template<class T, std::size_t N>
auto array_as_tie(std::array<T, N> &a) {
return detail::array_as_tie(a, std::make_index_sequence<N>());
};
// various overloads for different combinations of lvalues and rvalues - needs some work
// for instance, does not handle mixed lvalues and rvalues yet
template<class T, std::size_t N1, std::size_t N2>
auto array_cat(std::array<T, N1> &a1, std::array<T, N2> &a2) {
auto tied = std::tuple_cat(array_as_tie(a1), array_as_tie(a2));
return detail::copy_to_array<T>(tied, std::make_index_sequence<N1 + N2>());
};
template<class T, std::size_t N1, std::size_t N2>
auto array_cat(std::array<T, N1> &&a1, std::array<T, N2> &&a2) {
auto tied = std::tuple_cat(array_as_tie(a1), array_as_tie(a2));
return detail::move_to_array<T>(tied, std::make_index_sequence<N1 + N2>());
};
int main() {
std::array<int, 3> ar1 = {1, 2, 3};
std::array<int, 2> ar2 = {4, 5};
auto result = array_cat(ar1, ar2);
for (auto &x : result)
std::cout << x << " ";
std::cout << std::endl;
// move-construction
auto r2 = array_cat(std::array<std::string, 2> {"a", "b"},
std::array<std::string, 2>{"asdfghjk", "qwertyui"});
std::cout << "string result:\n";
for (auto &&x : r2)
std::cout << x << " ";
std::cout << std::endl;
return 0;
}
expected results:
1 2 3 4 5
string result:
a b asdfghjk qwertyui
A more concise evolution of #Constructor's C++17 solution with the added benefit that Type is not required to be default constructible
template <typename Type, std::size_t... sizes>
constexpr auto concatenate(const std::array<Type, sizes>&... arrays)
{
return std::apply(
[] (auto... elems) -> std::array<Type, (sizes + ...)> { return {{ elems... }}; },
std::tuple_cat(std::tuple_cat(arrays)...));
}
C++14.
template<std::size_t I>
using index_t=std::integral_constant<std::size_t, I>;
template<std::size_t I>
constexpr index_t<I> index{};
template<std::size_t...Is>
auto index_over(std::index_sequence<Is...>){
return [](auto&&f)->decltype(auto){
return decltype(f)(f)( index<Is>... );
};
}
template<std::size_t N>
auto index_upto(index_t<N>={}){
return index_over(std::make_index_sequence<N>{});
}
this lets us expand parameter packs inline.
template<std::size_t, class T>
using indexed_type=T;
template<class T>
std::decay_t<T> concat_arrays( T&& in ){ return std::forward<T>(in); }
template<class T, std::size_t N0, std::size_t N1 >
std::array<T, N0+N1>
concat_arrays( std::array<T,N0> arr0, std::array<T,N1> arr1 ){
auto idx0 = index_upto<N0>();
auto idx1 = index_upto<N1>();
return idx0( [&](auto...I0s){
return idx1( [&](auto...I1s)->std::array<T, N0+N1>{
return {{
arr0[I0s]...,
arr1[I1s]...
}};
})
});
}
which gets us to two. For N, the easy way is:
template<class T, std::size_t N0, std::size_t N1, std::size_t...Ns >
auto concat_arrays( std::array<T,N0> arr0, std::array<T,N1> arr1, std::array<T, Ns>... arrs ){
return concat_arrays( std::move(arr0), concat_arrays( std::move(arr1), std::move(arrs)... ) );
}
but it should be possible without recursion.
Code not tested.
C++17 solution that is constexpr and works correctly with moveably-only types.
template<class Array>
inline constexpr auto array_size = std::tuple_size_v<std::remove_reference_t<Array>>;
template<typename... Ts>
constexpr auto make_array(Ts&&... values)
{
using T = std::common_type_t<Ts...>;
return std::array<T, sizeof...(Ts)>{static_cast<T>(std::forward<Ts>(values))...};
}
namespace detail
{
template<typename Arr1, typename Arr2, std::size_t... is1, std::size_t... is2>
constexpr auto array_cat(Arr1&& arr1, Arr2&& arr2, std::index_sequence<is1...>, std::index_sequence<is2...>)
{
return make_array(std::get<is1>(std::forward<Arr1>(arr1))...,
std::get<is2>(std::forward<Arr2>(arr2))...);
}
}
template<typename Arr, typename... Arrs>
constexpr auto array_cat(Arr&& arr, Arrs&&... arrs)
{
if constexpr (sizeof...(Arrs) == 0)
return std::forward<Arr>(arr);
else if constexpr (sizeof...(Arrs) == 1)
return detail::array_cat(std::forward<Arr>(arr), std::forward<Arrs>(arrs)...,
std::make_index_sequence<array_size<Arr>>{},
std::make_index_sequence<array_size<Arrs...>>{});
else
return array_cat(std::forward<Arr>(arr), array_cat(std::forward<Arrs>(arrs)...));
}
Strictly C++11; not as readable as #Jarod42's, but potentially much more efficient with many arrays if the call-tree isn't fully flattened (in terms of inlining) since only one result object exists rather than multiple temporary, progressively-growing result objects:
namespace detail {
template<std::size_t...>
struct sum_sizes_;
template<std::size_t Acc>
struct sum_sizes_<Acc> : std::integral_constant<std::size_t, Acc> { };
template<std::size_t Acc, std::size_t N, std::size_t... Ns>
struct sum_sizes_<Acc, N, Ns...> : sum_sizes_<Acc + N, Ns...> { };
template<typename... As>
using sum_sizes_t = typename sum_sizes_<
0, std::tuple_size<typename std::decay<As>::type>{}...
>::type;
template<std::size_t O, typename A, typename R>
void transfer(R& ret, typename std::remove_reference<A>::type const& a) {
std::copy(a.begin(), a.end(), ret.begin() + O);
}
template<std::size_t O, typename A, typename R>
void transfer(R& ret, typename std::remove_reference<A>::type&& a) {
std::move(a.begin(), a.end(), ret.begin() + O);
}
template<std::size_t, typename R>
void concat(R const&) { }
template<std::size_t O, typename R, typename A, typename... As>
void concat(R& ret, A&& a, As&&... as) {
transfer<O, A>(ret, std::forward<A>(a));
concat<(O + sum_sizes_t<A>{})>(ret, std::forward<As>(as)...);
}
}
template<typename... As, typename std::enable_if<(sizeof...(As) >= 2), int>::type = 0>
auto concat(As&&... as)
-> std::array<
typename std::common_type<typename std::decay<As>::type::value_type...>::type,
detail::sum_sizes_t<As...>{}
> {
decltype(concat(std::forward<As>(as)...)) ret;
detail::concat<0>(ret, std::forward<As>(as)...);
return ret;
}
Online Demo
Note that this also forwards properly by using the std::move algorithm for rvalues rather than std::copy.
This doesn't generalize, but takes advantage of the fact that if we splat two arrays inside a set of braces, we can use that to initialize a new array.
I'm not sure how useful generalizing is, in any case. Given a bunch of arrays of mismatched sizes, just what else is there to do with them but join them all together?
#include <array>
#include <iostream>
#include <utility>
template<typename T, std::size_t L, std::size_t... Ls,
std::size_t R, std::size_t... Rs>
constexpr std::array<T, L + R> concat_aux(const std::array<T, L>& l, std::index_sequence<Ls...>,
const std::array<T, R>& r, std::index_sequence<Rs...>) {
return std::array<T, L + R> { std::get<Ls>(l)..., std::get<Rs>(r)... };
}
template<typename T, std::size_t L, std::size_t R>
constexpr std::array<T, L + R> concat(const std::array<T, L>& l, const std::array<T, R>& r) {
return concat_aux(l, std::make_index_sequence<L>{},
r, std::make_index_sequence<R>{});
}
template<typename T, std::size_t L, std::size_t R, std::size_t... Sizes>
constexpr auto concat(const std::array<T, L>& l,
const std::array<T, R>& r,
const std::array<T, Sizes>&... arrays) {
return concat(concat(l, r), arrays...);
}
int main() {
std::array<int, 5> a1{1, 2, 3, 4, 5};
std::array<int, 3> a2{6, 7, 8};
std::array<int, 2> a3{9, 10};
for (const auto& elem : concat(a1, a2, a3)) {
std::cout << elem << " ";
}
}

How do i use an iterator to access data within a tuple [duplicate]

How can I iterate over a tuple (using C++11)? I tried the following:
for(int i=0; i<std::tuple_size<T...>::value; ++i)
std::get<i>(my_tuple).do_sth();
but this doesn't work:
Error 1: sorry, unimplemented: cannot expand ‘Listener ...’ into a fixed-length argument list.
Error 2: i cannot appear in a constant expression.
So, how do I correctly iterate over the elements of a tuple?
I have an answer based on Iterating over a Tuple:
#include <tuple>
#include <utility>
#include <iostream>
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type
print(std::tuple<Tp...>& t)
{ }
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I < sizeof...(Tp), void>::type
print(std::tuple<Tp...>& t)
{
std::cout << std::get<I>(t) << std::endl;
print<I + 1, Tp...>(t);
}
int
main()
{
typedef std::tuple<int, float, double> T;
T t = std::make_tuple(2, 3.14159F, 2345.678);
print(t);
}
The usual idea is to use compile time recursion. In fact, this idea is used to make a printf that is type safe as noted in the original tuple papers.
This can be easily generalized into a for_each for tuples:
#include <tuple>
#include <utility>
template<std::size_t I = 0, typename FuncT, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type
for_each(std::tuple<Tp...> &, FuncT) // Unused arguments are given no names.
{ }
template<std::size_t I = 0, typename FuncT, typename... Tp>
inline typename std::enable_if<I < sizeof...(Tp), void>::type
for_each(std::tuple<Tp...>& t, FuncT f)
{
f(std::get<I>(t));
for_each<I + 1, FuncT, Tp...>(t, f);
}
Though this then requires some effort to have FuncT represent something with the appropriate overloads for every type the tuple might contain. This works best if you know all the tuple elements will share a common base class or something similar.
In C++17, you can use std::apply with fold expression:
std::apply([](auto&&... args) {((/* args.dosomething() */), ...);}, the_tuple);
A complete example for printing a tuple:
#include <tuple>
#include <iostream>
int main()
{
std::tuple t{42, 'a', 4.2}; // Another C++17 feature: class template argument deduction
std::apply([](auto&&... args) {((std::cout << args << '\n'), ...);}, t);
}
[Online Example on Coliru]
This solution solves the issue of evaluation order in M. Alaggan's answer.
C++ is introducing expansion statements for this purpose. They were originally on track for C++20 but narrowly missed the cut due to a lack of time for language wording review (see here and here).
The currently agreed syntax (see the links above) is:
{
auto tup = std::make_tuple(0, 'a', 3.14);
template for (auto elem : tup)
std::cout << elem << std::endl;
}
Boost.Fusion is a possibility:
Untested example:
struct DoSomething
{
template<typename T>
void operator()(T& t) const
{
t.do_sth();
}
};
tuple<....> t = ...;
boost::fusion::for_each(t, DoSomething());
In C++17 you can do this:
std::apply([](auto ...x){std::make_tuple(x.do_something()...);} , the_tuple);
This already works in Clang++ 3.9, using std::experimental::apply.
A more simple, intuitive and compiler-friendly way of doing this in C++17, using if constexpr:
// prints every element of a tuple
template<size_t I = 0, typename... Tp>
void print(std::tuple<Tp...>& t) {
std::cout << std::get<I>(t) << " ";
// do things
if constexpr(I+1 != sizeof...(Tp))
print<I+1>(t);
}
This is compile-time recursion, similar to the one presented by #emsr. But this doesn't use SFINAE so (I think) it is more compiler-friendly.
Use Boost.Hana and generic lambdas:
#include <tuple>
#include <iostream>
#include <boost/hana.hpp>
#include <boost/hana/ext/std/tuple.hpp>
struct Foo1 {
int foo() const { return 42; }
};
struct Foo2 {
int bar = 0;
int foo() { bar = 24; return bar; }
};
int main() {
using namespace std;
using boost::hana::for_each;
Foo1 foo1;
Foo2 foo2;
for_each(tie(foo1, foo2), [](auto &foo) {
cout << foo.foo() << endl;
});
cout << "foo2.bar after mutation: " << foo2.bar << endl;
}
http://coliru.stacked-crooked.com/a/27b3691f55caf271
Here's an easy C++17 way of iterating over tuple items with just standard library:
#include <tuple> // std::tuple
#include <functional> // std::invoke
template <
size_t Index = 0, // start iteration at 0 index
typename TTuple, // the tuple type
size_t Size =
std::tuple_size_v<
std::remove_reference_t<TTuple>>, // tuple size
typename TCallable, // the callable to be invoked for each tuple item
typename... TArgs // other arguments to be passed to the callable
>
void for_each(TTuple&& tuple, TCallable&& callable, TArgs&&... args)
{
if constexpr (Index < Size)
{
std::invoke(callable, args..., std::get<Index>(tuple));
if constexpr (Index + 1 < Size)
for_each<Index + 1>(
std::forward<TTuple>(tuple),
std::forward<TCallable>(callable),
std::forward<TArgs>(args)...);
}
}
Example:
#include <iostream>
int main()
{
std::tuple<int, char> items{1, 'a'};
for_each(items, [](const auto& item) {
std::cout << item << "\n";
});
}
Output:
1
a
This can be extended to conditionally break the loop in case the callable returns a value (but still work with callables that do not return a bool assignable value, e.g. void):
#include <tuple> // std::tuple
#include <functional> // std::invoke
template <
size_t Index = 0, // start iteration at 0 index
typename TTuple, // the tuple type
size_t Size =
std::tuple_size_v<
std::remove_reference_t<TTuple>>, // tuple size
typename TCallable, // the callable to bo invoked for each tuple item
typename... TArgs // other arguments to be passed to the callable
>
void for_each(TTuple&& tuple, TCallable&& callable, TArgs&&... args)
{
if constexpr (Index < Size)
{
if constexpr (std::is_assignable_v<bool&, std::invoke_result_t<TCallable&&, TArgs&&..., decltype(std::get<Index>(tuple))>>)
{
if (!std::invoke(callable, args..., std::get<Index>(tuple)))
return;
}
else
{
std::invoke(callable, args..., std::get<Index>(tuple));
}
if constexpr (Index + 1 < Size)
for_each<Index + 1>(
std::forward<TTuple>(tuple),
std::forward<TCallable>(callable),
std::forward<TArgs>(args)...);
}
}
Example:
#include <iostream>
int main()
{
std::tuple<int, char> items{ 1, 'a' };
for_each(items, [](const auto& item) {
std::cout << item << "\n";
});
std::cout << "---\n";
for_each(items, [](const auto& item) {
std::cout << item << "\n";
return false;
});
}
Output:
1
a
---
1
You need to use template metaprogramming, here shown with Boost.Tuple:
#include <boost/tuple/tuple.hpp>
#include <iostream>
template <typename T_Tuple, size_t size>
struct print_tuple_helper {
static std::ostream & print( std::ostream & s, const T_Tuple & t ) {
return print_tuple_helper<T_Tuple,size-1>::print( s, t ) << boost::get<size-1>( t );
}
};
template <typename T_Tuple>
struct print_tuple_helper<T_Tuple,0> {
static std::ostream & print( std::ostream & s, const T_Tuple & ) {
return s;
}
};
template <typename T_Tuple>
std::ostream & print_tuple( std::ostream & s, const T_Tuple & t ) {
return print_tuple_helper<T_Tuple,boost::tuples::length<T_Tuple>::value>::print( s, t );
}
int main() {
const boost::tuple<int,char,float,char,double> t( 0, ' ', 2.5f, '\n', 3.1416 );
print_tuple( std::cout, t );
return 0;
}
In C++0x, you can write print_tuple() as a variadic template function instead.
First define some index helpers:
template <size_t ...I>
struct index_sequence {};
template <size_t N, size_t ...I>
struct make_index_sequence : public make_index_sequence<N - 1, N - 1, I...> {};
template <size_t ...I>
struct make_index_sequence<0, I...> : public index_sequence<I...> {};
With your function you would like to apply on each tuple element:
template <typename T>
/* ... */ foo(T t) { /* ... */ }
you can write:
template<typename ...T, size_t ...I>
/* ... */ do_foo_helper(std::tuple<T...> &ts, index_sequence<I...>) {
std::tie(foo(std::get<I>(ts)) ...);
}
template <typename ...T>
/* ... */ do_foo(std::tuple<T...> &ts) {
return do_foo_helper(ts, make_index_sequence<sizeof...(T)>());
}
Or if foo returns void, use
std::tie((foo(std::get<I>(ts)), 1) ... );
Note: On C++14 make_index_sequence is already defined (http://en.cppreference.com/w/cpp/utility/integer_sequence).
If you do need a left-to-right evaluation order, consider something like this:
template <typename T, typename ...R>
void do_foo_iter(T t, R ...r) {
foo(t);
do_foo(r...);
}
void do_foo_iter() {}
template<typename ...T, size_t ...I>
void do_foo_helper(std::tuple<T...> &ts, index_sequence<I...>) {
do_foo_iter(std::get<I>(ts) ...);
}
template <typename ...T>
void do_foo(std::tuple<T...> &ts) {
do_foo_helper(ts, make_index_sequence<sizeof...(T)>());
}
If you want to use std::tuple and you have C++ compiler which supports variadic templates, try code bellow (tested with g++4.5). This should be the answer to your question.
#include <tuple>
// ------------- UTILITY---------------
template<int...> struct index_tuple{};
template<int I, typename IndexTuple, typename... Types>
struct make_indexes_impl;
template<int I, int... Indexes, typename T, typename ... Types>
struct make_indexes_impl<I, index_tuple<Indexes...>, T, Types...>
{
typedef typename make_indexes_impl<I + 1, index_tuple<Indexes..., I>, Types...>::type type;
};
template<int I, int... Indexes>
struct make_indexes_impl<I, index_tuple<Indexes...> >
{
typedef index_tuple<Indexes...> type;
};
template<typename ... Types>
struct make_indexes : make_indexes_impl<0, index_tuple<>, Types...>
{};
// ----------- FOR EACH -----------------
template<typename Func, typename Last>
void for_each_impl(Func&& f, Last&& last)
{
f(last);
}
template<typename Func, typename First, typename ... Rest>
void for_each_impl(Func&& f, First&& first, Rest&&...rest)
{
f(first);
for_each_impl( std::forward<Func>(f), rest...);
}
template<typename Func, int ... Indexes, typename ... Args>
void for_each_helper( Func&& f, index_tuple<Indexes...>, std::tuple<Args...>&& tup)
{
for_each_impl( std::forward<Func>(f), std::forward<Args>(std::get<Indexes>(tup))...);
}
template<typename Func, typename ... Args>
void for_each( std::tuple<Args...>& tup, Func&& f)
{
for_each_helper(std::forward<Func>(f),
typename make_indexes<Args...>::type(),
std::forward<std::tuple<Args...>>(tup) );
}
template<typename Func, typename ... Args>
void for_each( std::tuple<Args...>&& tup, Func&& f)
{
for_each_helper(std::forward<Func>(f),
typename make_indexes<Args...>::type(),
std::forward<std::tuple<Args...>>(tup) );
}
boost::fusion is another option, but it requires its own tuple type: boost::fusion::tuple. Lets better stick to the standard! Here is a test:
#include <iostream>
// ---------- FUNCTOR ----------
struct Functor
{
template<typename T>
void operator()(T& t) const { std::cout << t << std::endl; }
};
int main()
{
for_each( std::make_tuple(2, 0.6, 'c'), Functor() );
return 0;
}
the power of variadic templates!
In MSVC STL there's a _For_each_tuple_element function (not documented):
#include <tuple>
// ...
std::tuple<int, char, float> values{};
std::_For_each_tuple_element(values, [](auto&& value)
{
// process 'value'
});
Another option would be to implement iterators for tuples. This has the advantage that you can use a variety of algorithms provided by the standard library and range-based for loops. An elegant approach to this is explained here https://foonathan.net/2017/03/tuple-iterator/. The basic idea is to turn tuples into a range with begin() and end() methods to provide iterators. The iterator itself returns a std::variant<...> which can then be visited using std::visit.
Here some examples:
auto t = std::tuple{ 1, 2.f, 3.0 };
auto r = to_range(t);
for(auto v : r)
{
std::visit(unwrap([](auto& x)
{
x = 1;
}), v);
}
std::for_each(begin(r), end(r), [](auto v)
{
std::visit(unwrap([](auto& x)
{
x = 0;
}), v);
});
std::accumulate(begin(r), end(r), 0.0, [](auto acc, auto v)
{
return acc + std::visit(unwrap([](auto& x)
{
return static_cast<double>(x);
}), v);
});
std::for_each(begin(r), end(r), [](auto v)
{
std::visit(unwrap([](const auto& x)
{
std::cout << x << std::endl;
}), v);
});
std::for_each(begin(r), end(r), [](auto v)
{
std::visit(overload(
[](int x) { std::cout << "int" << std::endl; },
[](float x) { std::cout << "float" << std::endl; },
[](double x) { std::cout << "double" << std::endl; }), v);
});
My implementation (which is heavily based on the explanations in the link above):
#ifndef TUPLE_RANGE_H
#define TUPLE_RANGE_H
#include <utility>
#include <functional>
#include <variant>
#include <type_traits>
template<typename Accessor>
class tuple_iterator
{
public:
tuple_iterator(Accessor acc, const int idx)
: acc_(acc), index_(idx)
{
}
tuple_iterator operator++()
{
++index_;
return *this;
}
template<typename T>
bool operator ==(tuple_iterator<T> other)
{
return index_ == other.index();
}
template<typename T>
bool operator !=(tuple_iterator<T> other)
{
return index_ != other.index();
}
auto operator*() { return std::invoke(acc_, index_); }
[[nodiscard]] int index() const { return index_; }
private:
const Accessor acc_;
int index_;
};
template<bool IsConst, typename...Ts>
struct tuple_access
{
using tuple_type = std::tuple<Ts...>;
using tuple_ref = std::conditional_t<IsConst, const tuple_type&, tuple_type&>;
template<typename T>
using element_ref = std::conditional_t<IsConst,
std::reference_wrapper<const T>,
std::reference_wrapper<T>>;
using variant_type = std::variant<element_ref<Ts>...>;
using function_type = variant_type(*)(tuple_ref);
using table_type = std::array<function_type, sizeof...(Ts)>;
private:
template<size_t Index>
static constexpr function_type create_accessor()
{
return { [](tuple_ref t) -> variant_type
{
if constexpr (IsConst)
return std::cref(std::get<Index>(t));
else
return std::ref(std::get<Index>(t));
} };
}
template<size_t...Is>
static constexpr table_type create_table(std::index_sequence<Is...>)
{
return { create_accessor<Is>()... };
}
public:
static constexpr auto table = create_table(std::make_index_sequence<sizeof...(Ts)>{});
};
template<bool IsConst, typename...Ts>
class tuple_range
{
public:
using tuple_access_type = tuple_access<IsConst, Ts...>;
using tuple_ref = typename tuple_access_type::tuple_ref;
static constexpr auto tuple_size = sizeof...(Ts);
explicit tuple_range(tuple_ref tuple)
: tuple_(tuple)
{
}
[[nodiscard]] auto begin() const
{
return tuple_iterator{ create_accessor(), 0 };
}
[[nodiscard]] auto end() const
{
return tuple_iterator{ create_accessor(), tuple_size };
}
private:
tuple_ref tuple_;
auto create_accessor() const
{
return [this](int idx)
{
return std::invoke(tuple_access_type::table[idx], tuple_);
};
}
};
template<bool IsConst, typename...Ts>
auto begin(const tuple_range<IsConst, Ts...>& r)
{
return r.begin();
}
template<bool IsConst, typename...Ts>
auto end(const tuple_range<IsConst, Ts...>& r)
{
return r.end();
}
template <class ... Fs>
struct overload : Fs... {
explicit overload(Fs&&... fs) : Fs{ fs }... {}
using Fs::operator()...;
template<class T>
auto operator()(std::reference_wrapper<T> ref)
{
return (*this)(ref.get());
}
template<class T>
auto operator()(std::reference_wrapper<const T> ref)
{
return (*this)(ref.get());
}
};
template <class F>
struct unwrap : overload<F>
{
explicit unwrap(F&& f) : overload<F>{ std::forward<F>(f) } {}
using overload<F>::operator();
};
template<typename...Ts>
auto to_range(std::tuple<Ts...>& t)
{
return tuple_range<false, Ts...>{t};
}
template<typename...Ts>
auto to_range(const std::tuple<Ts...>& t)
{
return tuple_range<true, Ts...>{t};
}
#endif
Read-only access is also supported by passing a const std::tuple<>& to to_range().
Others have mentioned some well-designed third-party libraries that you may turn to. However, if you are using C++ without those third-party libraries, the following code may help.
namespace detail {
template <class Tuple, std::size_t I, class = void>
struct for_each_in_tuple_helper {
template <class UnaryFunction>
static void apply(Tuple&& tp, UnaryFunction& f) {
f(std::get<I>(std::forward<Tuple>(tp)));
for_each_in_tuple_helper<Tuple, I + 1u>::apply(std::forward<Tuple>(tp), f);
}
};
template <class Tuple, std::size_t I>
struct for_each_in_tuple_helper<Tuple, I, typename std::enable_if<
I == std::tuple_size<typename std::decay<Tuple>::type>::value>::type> {
template <class UnaryFunction>
static void apply(Tuple&&, UnaryFunction&) {}
};
} // namespace detail
template <class Tuple, class UnaryFunction>
UnaryFunction for_each_in_tuple(Tuple&& tp, UnaryFunction f) {
detail::for_each_in_tuple_helper<Tuple, 0u>
::apply(std::forward<Tuple>(tp), f);
return std::move(f);
}
Note: The code compiles with any compiler supporing C++11, and it keeps consistency with design of the standard library:
The tuple need not be std::tuple, and instead may be anything that supports std::get and std::tuple_size; in particular, std::array and std::pair may be used;
The tuple may be a reference type or cv-qualified;
It has similar behavior as std::for_each, and returns the input UnaryFunction;
For C++14 (or laster version) users, typename std::enable_if<T>::type and typename std::decay<T>::type could be replaced with their simplified version, std::enable_if_t<T> and std::decay_t<T>;
For C++17 (or laster version) users, std::tuple_size<T>::value could be replaced with its simplified version, std::tuple_size_v<T>.
For C++20 (or laster version) users, the SFINAE feature could be implemented with the Concepts.
Using constexpr and if constexpr(C++17) this is fairly simple and straight forward:
template <std::size_t I = 0, typename ... Ts>
void print(std::tuple<Ts...> tup) {
if constexpr (I == sizeof...(Ts)) {
return;
} else {
std::cout << std::get<I>(tup) << ' ';
print<I+1>(tup);
}
}
I might have missed this train, but this will be here for future reference.
Here's my construct based on this answer and on this gist:
#include <tuple>
#include <utility>
template<std::size_t N>
struct tuple_functor
{
template<typename T, typename F>
static void run(std::size_t i, T&& t, F&& f)
{
const std::size_t I = (N - 1);
switch(i)
{
case I:
std::forward<F>(f)(std::get<I>(std::forward<T>(t)));
break;
default:
tuple_functor<I>::run(i, std::forward<T>(t), std::forward<F>(f));
}
}
};
template<>
struct tuple_functor<0>
{
template<typename T, typename F>
static void run(std::size_t, T, F){}
};
You then use it as follow:
template<typename... T>
void logger(std::string format, T... args) //behaves like C#'s String.Format()
{
auto tp = std::forward_as_tuple(args...);
auto fc = [](const auto& t){std::cout << t;};
/* ... */
std::size_t some_index = ...
tuple_functor<sizeof...(T)>::run(some_index, tp, fc);
/* ... */
}
There could be room for improvements.
As per OP's code, it would become this:
const std::size_t num = sizeof...(T);
auto my_tuple = std::forward_as_tuple(t...);
auto do_sth = [](const auto& elem){/* ... */};
for(int i = 0; i < num; ++i)
tuple_functor<num>::run(i, my_tuple, do_sth);
Of all the answers I've seen here, here and here, I liked #sigidagi's way of iterating best. Unfortunately, his answer is very verbose which in my opinion obscures the inherent clarity.
This is my version of his solution which is more concise and works with std::tuple, std::pair and std::array.
template<typename UnaryFunction>
void invoke_with_arg(UnaryFunction)
{}
/**
* Invoke the unary function with each of the arguments in turn.
*/
template<typename UnaryFunction, typename Arg0, typename... Args>
void invoke_with_arg(UnaryFunction f, Arg0&& a0, Args&&... as)
{
f(std::forward<Arg0>(a0));
invoke_with_arg(std::move(f), std::forward<Args>(as)...);
}
template<typename Tuple, typename UnaryFunction, std::size_t... Indices>
void for_each_helper(Tuple&& t, UnaryFunction f, std::index_sequence<Indices...>)
{
using std::get;
invoke_with_arg(std::move(f), get<Indices>(std::forward<Tuple>(t))...);
}
/**
* Invoke the unary function for each of the elements of the tuple.
*/
template<typename Tuple, typename UnaryFunction>
void for_each(Tuple&& t, UnaryFunction f)
{
using size = std::tuple_size<typename std::remove_reference<Tuple>::type>;
for_each_helper(
std::forward<Tuple>(t),
std::move(f),
std::make_index_sequence<size::value>()
);
}
Demo: coliru
C++14's std::make_index_sequence can be implemented for C++11.
Expanding on #Stypox answer, we can make their solution more generic (C++17 onward). By adding a callable function argument:
template<size_t I = 0, typename... Tp, typename F>
void for_each_apply(std::tuple<Tp...>& t, F &&f) {
f(std::get<I>(t));
if constexpr(I+1 != sizeof...(Tp)) {
for_each_apply<I+1>(t, std::forward<F>(f));
}
}
Then, we need a strategy to visit each type.
Let start with some helpers (first two taken from cppreference):
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
template<class ... Ts> struct variant_ref { using type = std::variant<std::reference_wrapper<Ts>...>; };
variant_ref is used to allow tuples' state to be modified.
Usage:
std::tuple<Foo, Bar, Foo> tuples;
for_each_apply(tuples,
[](variant_ref<Foo, Bar>::type &&v) {
std::visit(overloaded {
[](Foo &arg) { arg.foo(); },
[](Bar const &arg) { arg.bar(); },
}, v);
});
Result:
Foo0
Bar
Foo0
Foo1
Bar
Foo1
For completeness, here are my Bar & Foo:
struct Foo {
void foo() {std::cout << "Foo" << i++ << std::endl;}
int i = 0;
};
struct Bar {
void bar() const {std::cout << "Bar" << std::endl;}
};
I have stumbled on the same problem for iterating over a tuple of function objects, so here is one more solution:
#include <tuple>
#include <iostream>
// Function objects
class A
{
public:
inline void operator()() const { std::cout << "A\n"; };
};
class B
{
public:
inline void operator()() const { std::cout << "B\n"; };
};
class C
{
public:
inline void operator()() const { std::cout << "C\n"; };
};
class D
{
public:
inline void operator()() const { std::cout << "D\n"; };
};
// Call iterator using recursion.
template<typename Fobjects, int N = 0>
struct call_functors
{
static void apply(Fobjects const& funcs)
{
std::get<N>(funcs)();
// Choose either the stopper or descend further,
// depending if N + 1 < size of the tuple.
using caller = std::conditional_t
<
N + 1 < std::tuple_size_v<Fobjects>,
call_functors<Fobjects, N + 1>,
call_functors<Fobjects, -1>
>;
caller::apply(funcs);
}
};
// Stopper.
template<typename Fobjects>
struct call_functors<Fobjects, -1>
{
static void apply(Fobjects const& funcs)
{
}
};
// Call dispatch function.
template<typename Fobjects>
void call(Fobjects const& funcs)
{
call_functors<Fobjects>::apply(funcs);
};
using namespace std;
int main()
{
using Tuple = tuple<A,B,C,D>;
Tuple functors = {A{}, B{}, C{}, D{}};
call(functors);
return 0;
}
Output:
A
B
C
D
There're many great answers, but for some reason most of them don't consider returning the results of applying f to our tuple...
or did I overlook it? Anyway, here's yet another way you can do that:
Doing Foreach with style (debatable)
auto t = std::make_tuple(1, "two", 3.f);
t | foreach([](auto v){ std::cout << v << " "; });
And returning from that:
auto t = std::make_tuple(1, "two", 3.f);
auto sizes = t | foreach([](auto v) {
return sizeof(v);
});
sizes | foreach([](auto v) {
std::cout << v;
});
Implementation (pretty simple one)
Edit: it gets a little messier.
I won't include some metaprogramming boilerplate here, for it will definitely make things less readable and besides, I believe those have already been answered somewhere on stackoverflow.
In case you're feeling lazy, feel free to peek into my github repo for implementation of both
#include <utility>
// Optional includes, if you don't want to implement it by hand or google it
// you can find it in the repo (link below)
#include "typesystem/typelist.hpp"
// used to check if all return types are void,
// making it a special case
// (and, alas, not using constexpr-if
// for the sake of being compatible with C++14...)
template <bool Cond, typename T, typename F>
using select = typename std::conditional<Cond, T, F>::type;
template <typename F>
struct elementwise_apply {
F f;
};
template <typename F>
constexpr auto foreach(F && f) -> elementwise_apply<F> { return {std::forward<F>(f)}; }
template <typename R>
struct tuple_map {
template <typename F, typename T, size_t... Is>
static constexpr decltype(auto) impl(std::index_sequence<Is...>, F && f, T&& tuple) {
return R{ std::forward<F>(f)( std::get<Is>(tuple) )... };
}
};
template<>
struct tuple_map<void> {
template <typename F, typename T, size_t... Is>
static constexpr void impl(std::index_sequence<Is...>, F && f, T&& tuple) {
[[maybe_unused]] std::initializer_list<int> _ {((void)std::forward<F>(f)( std::get<Is>(tuple) ), 0)... };
}
};
template <typename F, typename... Ts>
constexpr decltype(auto) operator| (std::tuple<Ts...> & t, fmap<F> && op) {
constexpr bool all_void = core::Types<decltype( std::move(op).f(std::declval<Ts&>()) )...>.all( core::is_void );
using R = meta::select<all_void, void, std::tuple<decltype(std::move(op).f(std::declval<Ts&>()))...>>;
return tuple_map<R>::impl(std::make_index_sequence<sizeof...(Ts)>{}, std::move(op).f, t);
}
template <typename F, typename... Ts>
constexpr decltype(auto) operator| (std::tuple<Ts...> const& t, fmap<F> && op) {
constexpr bool all_void = check if all "decltype( std::move(op).f(std::declval<Ts>()) )..." types are void, since then it's a special case
// e.g. core::Types<decltype( std::move(op).f(std::declval<Ts>()) )...>.all( core::is_void );
using R = meta::select<all_void, void, std::tuple<decltype(std::move(op).f(std::declval<Ts const&>()))...>>;
return tuple_map<R>::impl(std::make_index_sequence<sizeof...(Ts)>{}, std::move(op).f, t);
}
template <typename F, typename... Ts>
constexpr decltype(auto) operator| (std::tuple<Ts...> && t, fmap<F> && op) {
constexpr bool all_void = core::Types<decltype( std::move(op).f(std::declval<Ts&&>()) )...>.all( core::is_void );
using R = meta::select<all_void, void, std::tuple<decltype(std::move(op).f(std::declval<Ts&&>()))...>>;
return tuple_map<R>::impl(std::make_index_sequence<sizeof...(Ts)>{}, std::move(op).f, std::move(t));
}
Yeah, that would be much nicer if we were to use C++17
This is also an example of std::moving object's members, for which I'll better refer to this nice brief article
P.S. If you're stuck checking if all "decltype( std::move(op).f(std::declval()) )..." types are void
you can find some metaprogramming library, or, if those libraries seem too hard to grasp (which some of them may be due to some crazy metaprogramming tricks), you know where to look
template <typename F, typename T>
static constexpr size_t
foreach_in_tuple(std::tuple<T> & tuple, F && do_, size_t index_ = 0)
{
do_(tuple, index_);
return index_;
}
template <typename F, typename T, typename U, typename... Types>
static constexpr size_t
foreach_in_tuple(std::tuple<T,U,Types...> & tuple, F && do_, size_t index_ = 0)
{
if(!do_(tuple, index_))
return index_;
auto & next_tuple = reinterpret_cast<std::tuple<U,Types...> &>(tuple);
return foreach_in_tuple(next_tuple, std::forward<F>(do_), index_+1);
}
int main()
{
using namespace std;
auto tup = make_tuple(1, 2.3f, 'G', "hello");
foreach_in_tuple(tup, [](auto & tuple, size_t i)
{
auto & value = std::get<0>(tuple);
std::cout << i << " " << value << std::endl;
// if(i >= 2) return false; // break;
return true; // continue
});
}
Here is a solution based on std::interger_sequence.
As I don't know if my_tuple is constructed from std::make_tuple<T>(T &&...) in your code. It's essential for how to construct std::integer_sequence in the solution below.
(1) if your already have a my_tuple outside your function(not using template<typename ...T>), You can use
[](auto my_tuple)
{
[&my_tuple]<typename N, N... n>(std::integer_sequence<N, n...> int_seq)
{
((std::cout << std::get<n>(my_tuple) << '\n'), ...);
}(std::make_index_sequence<std::tuple_size_v<decltype(my_tuple)>>{});
}(std::make_tuple());
(2) if your havn't constructed my_tuple in your function and want to handle your T ...arguments
[]<typename ...T>(T... args)
{
[&args...]<typename N, N... n>(std::integer_sequence<N, n...> int_seq)
{
((std::cout << std::get<n>(std::forward_as_tuple(args...)) << '\n'), ...);
}(std::index_sequence_for<T...>{});
}();
boost's tuple provides helper functions get_head() and get_tail() so your helper functions may look like this:
inline void call_do_sth(const null_type&) {};
template <class H, class T>
inline void call_do_sth(cons<H, T>& x) { x.get_head().do_sth(); call_do_sth(x.get_tail()); }
as described in here http://www.boost.org/doc/libs/1_34_0/libs/tuple/doc/tuple_advanced_interface.html
with std::tuple it should be similar.
Actually, unfortunately std::tuple does not seem to provide such interface, so methods suggested before should work, or you would need to switch to boost::tuple which has other benefits (like io operators already provided). Though there is downside of boost::tuple with gcc - it does not accept variadic templates yet, but that may be already fixed as I do not have latest version of boost installed on my machine.

Initializing C++ std::array with smaller arrays

How can I construct an std::array out of several smaller ones, plus not-array elements?
I.e.:
std::array<std::string, 2> strings = { "a", "b" };
std::array<std::string, 2> more_strings = { "c", "d" };
std::string another_string = "e";
std::array<std::string, 5> result = {strings, more_strings, another_string};
The same question applies to initializing std::initializer_list with smaller std::initializer_lists.
If it's possible for you, you might find tuples easier (and more efficient) to work with until the final creation of the array.
conceptually, you could write something like this:
using namespace std;
auto strings = make_tuple( "a"s, "b"s );
auto more_strings = make_tuple( "c"s, "d"s);
auto another_string = make_tuple("e"s);
auto result = to_array(tuple_cat(strings, more_strings, another_string));
Of course you'll need an implementation for to_array which is not trivial. The full code is below, with credit going to Luc Danton in this answer:
Convert std::tuple to std::array C++11
full code for reference:
#include <iostream>
#include <string>
#include <tuple>
#include <array>
template<int... Indices>
struct indices {
using next = indices<Indices..., sizeof...(Indices)>;
};
template<int Size>
struct build_indices {
using type = typename build_indices<Size - 1>::type::next;
};
template<>
struct build_indices<0> {
using type = indices<>;
};
template<typename T>
using Bare = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
template<typename Tuple>
constexpr
typename build_indices<std::tuple_size<Bare<Tuple>>::value>::type
make_indices()
{ return {}; }
template<typename Tuple, int... Indices>
std::array<
typename std::tuple_element<0, Bare<Tuple>>::type,
std::tuple_size<Bare<Tuple>>::value
>
to_array(Tuple&& tuple, indices<Indices...>)
{
using std::get;
return {{ get<Indices>(std::forward<Tuple>(tuple))... }};
}
template<typename Tuple>
auto to_array(Tuple&& tuple)
-> decltype( to_array(std::declval<Tuple>(), make_indices<Tuple>()) )
{
return to_array(std::forward<Tuple>(tuple), make_indices<Tuple>());
}
auto main() -> int
{
using namespace std;
auto strings = make_tuple( "a"s, "b"s );
auto more_strings = make_tuple( "c"s, "d"s);
auto another_string = make_tuple("e"s);
auto result = to_array(tuple_cat(strings, more_strings, another_string));
for (const auto& e : result)
{
cout << e << endl;
}
return 0;
}
Here is a function that can join std::arrays.
template<typename T>
auto wrap_value(T&& value)
{
return std::tuple<T&&>(std::forward<T>(value));
}
template<typename T, std::size_t N>
std::array<T, N>& wrap_value(std::array<T, N>& value)
{
return value;
}
template<typename T, std::size_t N>
std::array<T, N> const& wrap_value(std::array<T, N> const& value)
{
return value;
}
template<typename T, std::size_t N>
std::array<T, N>&& wrap_value(std::array<T, N>&& value)
{
return std::move(value);
}
template<std::size_t... Is, typename... Ts>
std::array<std::common_type_t<Ts...>, sizeof...(Is)>
join_arrays_impl(std::index_sequence<Is...>, std::tuple<Ts...>&& parts)
{
return {std::get<Is>(std::move(parts))...};
}
template<typename... Ts>
auto join_arrays(Ts&&... parts)
{
auto wrapped_parts = std::tuple_cat((wrap_value)(std::forward<Ts>(parts))...);
constexpr auto size = std::tuple_size<decltype(wrapped_parts)>::value;
std::make_index_sequence<size> seq;
return (join_arrays_impl)(seq, std::move(wrapped_parts));
}
I don't think you can implement a similar function for std::initializer_lists. See it working here.

Iterate over a c++14 tuple with a lambda by using boost::mpl::for_each [duplicate]

How can I iterate over a tuple (using C++11)? I tried the following:
for(int i=0; i<std::tuple_size<T...>::value; ++i)
std::get<i>(my_tuple).do_sth();
but this doesn't work:
Error 1: sorry, unimplemented: cannot expand ‘Listener ...’ into a fixed-length argument list.
Error 2: i cannot appear in a constant expression.
So, how do I correctly iterate over the elements of a tuple?
I have an answer based on Iterating over a Tuple:
#include <tuple>
#include <utility>
#include <iostream>
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type
print(std::tuple<Tp...>& t)
{ }
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I < sizeof...(Tp), void>::type
print(std::tuple<Tp...>& t)
{
std::cout << std::get<I>(t) << std::endl;
print<I + 1, Tp...>(t);
}
int
main()
{
typedef std::tuple<int, float, double> T;
T t = std::make_tuple(2, 3.14159F, 2345.678);
print(t);
}
The usual idea is to use compile time recursion. In fact, this idea is used to make a printf that is type safe as noted in the original tuple papers.
This can be easily generalized into a for_each for tuples:
#include <tuple>
#include <utility>
template<std::size_t I = 0, typename FuncT, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type
for_each(std::tuple<Tp...> &, FuncT) // Unused arguments are given no names.
{ }
template<std::size_t I = 0, typename FuncT, typename... Tp>
inline typename std::enable_if<I < sizeof...(Tp), void>::type
for_each(std::tuple<Tp...>& t, FuncT f)
{
f(std::get<I>(t));
for_each<I + 1, FuncT, Tp...>(t, f);
}
Though this then requires some effort to have FuncT represent something with the appropriate overloads for every type the tuple might contain. This works best if you know all the tuple elements will share a common base class or something similar.
In C++17, you can use std::apply with fold expression:
std::apply([](auto&&... args) {((/* args.dosomething() */), ...);}, the_tuple);
A complete example for printing a tuple:
#include <tuple>
#include <iostream>
int main()
{
std::tuple t{42, 'a', 4.2}; // Another C++17 feature: class template argument deduction
std::apply([](auto&&... args) {((std::cout << args << '\n'), ...);}, t);
}
[Online Example on Coliru]
This solution solves the issue of evaluation order in M. Alaggan's answer.
C++ is introducing expansion statements for this purpose. They were originally on track for C++20 but narrowly missed the cut due to a lack of time for language wording review (see here and here).
The currently agreed syntax (see the links above) is:
{
auto tup = std::make_tuple(0, 'a', 3.14);
template for (auto elem : tup)
std::cout << elem << std::endl;
}
Boost.Fusion is a possibility:
Untested example:
struct DoSomething
{
template<typename T>
void operator()(T& t) const
{
t.do_sth();
}
};
tuple<....> t = ...;
boost::fusion::for_each(t, DoSomething());
In C++17 you can do this:
std::apply([](auto ...x){std::make_tuple(x.do_something()...);} , the_tuple);
This already works in Clang++ 3.9, using std::experimental::apply.
A more simple, intuitive and compiler-friendly way of doing this in C++17, using if constexpr:
// prints every element of a tuple
template<size_t I = 0, typename... Tp>
void print(std::tuple<Tp...>& t) {
std::cout << std::get<I>(t) << " ";
// do things
if constexpr(I+1 != sizeof...(Tp))
print<I+1>(t);
}
This is compile-time recursion, similar to the one presented by #emsr. But this doesn't use SFINAE so (I think) it is more compiler-friendly.
Use Boost.Hana and generic lambdas:
#include <tuple>
#include <iostream>
#include <boost/hana.hpp>
#include <boost/hana/ext/std/tuple.hpp>
struct Foo1 {
int foo() const { return 42; }
};
struct Foo2 {
int bar = 0;
int foo() { bar = 24; return bar; }
};
int main() {
using namespace std;
using boost::hana::for_each;
Foo1 foo1;
Foo2 foo2;
for_each(tie(foo1, foo2), [](auto &foo) {
cout << foo.foo() << endl;
});
cout << "foo2.bar after mutation: " << foo2.bar << endl;
}
http://coliru.stacked-crooked.com/a/27b3691f55caf271
Here's an easy C++17 way of iterating over tuple items with just standard library:
#include <tuple> // std::tuple
#include <functional> // std::invoke
template <
size_t Index = 0, // start iteration at 0 index
typename TTuple, // the tuple type
size_t Size =
std::tuple_size_v<
std::remove_reference_t<TTuple>>, // tuple size
typename TCallable, // the callable to be invoked for each tuple item
typename... TArgs // other arguments to be passed to the callable
>
void for_each(TTuple&& tuple, TCallable&& callable, TArgs&&... args)
{
if constexpr (Index < Size)
{
std::invoke(callable, args..., std::get<Index>(tuple));
if constexpr (Index + 1 < Size)
for_each<Index + 1>(
std::forward<TTuple>(tuple),
std::forward<TCallable>(callable),
std::forward<TArgs>(args)...);
}
}
Example:
#include <iostream>
int main()
{
std::tuple<int, char> items{1, 'a'};
for_each(items, [](const auto& item) {
std::cout << item << "\n";
});
}
Output:
1
a
This can be extended to conditionally break the loop in case the callable returns a value (but still work with callables that do not return a bool assignable value, e.g. void):
#include <tuple> // std::tuple
#include <functional> // std::invoke
template <
size_t Index = 0, // start iteration at 0 index
typename TTuple, // the tuple type
size_t Size =
std::tuple_size_v<
std::remove_reference_t<TTuple>>, // tuple size
typename TCallable, // the callable to bo invoked for each tuple item
typename... TArgs // other arguments to be passed to the callable
>
void for_each(TTuple&& tuple, TCallable&& callable, TArgs&&... args)
{
if constexpr (Index < Size)
{
if constexpr (std::is_assignable_v<bool&, std::invoke_result_t<TCallable&&, TArgs&&..., decltype(std::get<Index>(tuple))>>)
{
if (!std::invoke(callable, args..., std::get<Index>(tuple)))
return;
}
else
{
std::invoke(callable, args..., std::get<Index>(tuple));
}
if constexpr (Index + 1 < Size)
for_each<Index + 1>(
std::forward<TTuple>(tuple),
std::forward<TCallable>(callable),
std::forward<TArgs>(args)...);
}
}
Example:
#include <iostream>
int main()
{
std::tuple<int, char> items{ 1, 'a' };
for_each(items, [](const auto& item) {
std::cout << item << "\n";
});
std::cout << "---\n";
for_each(items, [](const auto& item) {
std::cout << item << "\n";
return false;
});
}
Output:
1
a
---
1
You need to use template metaprogramming, here shown with Boost.Tuple:
#include <boost/tuple/tuple.hpp>
#include <iostream>
template <typename T_Tuple, size_t size>
struct print_tuple_helper {
static std::ostream & print( std::ostream & s, const T_Tuple & t ) {
return print_tuple_helper<T_Tuple,size-1>::print( s, t ) << boost::get<size-1>( t );
}
};
template <typename T_Tuple>
struct print_tuple_helper<T_Tuple,0> {
static std::ostream & print( std::ostream & s, const T_Tuple & ) {
return s;
}
};
template <typename T_Tuple>
std::ostream & print_tuple( std::ostream & s, const T_Tuple & t ) {
return print_tuple_helper<T_Tuple,boost::tuples::length<T_Tuple>::value>::print( s, t );
}
int main() {
const boost::tuple<int,char,float,char,double> t( 0, ' ', 2.5f, '\n', 3.1416 );
print_tuple( std::cout, t );
return 0;
}
In C++0x, you can write print_tuple() as a variadic template function instead.
First define some index helpers:
template <size_t ...I>
struct index_sequence {};
template <size_t N, size_t ...I>
struct make_index_sequence : public make_index_sequence<N - 1, N - 1, I...> {};
template <size_t ...I>
struct make_index_sequence<0, I...> : public index_sequence<I...> {};
With your function you would like to apply on each tuple element:
template <typename T>
/* ... */ foo(T t) { /* ... */ }
you can write:
template<typename ...T, size_t ...I>
/* ... */ do_foo_helper(std::tuple<T...> &ts, index_sequence<I...>) {
std::tie(foo(std::get<I>(ts)) ...);
}
template <typename ...T>
/* ... */ do_foo(std::tuple<T...> &ts) {
return do_foo_helper(ts, make_index_sequence<sizeof...(T)>());
}
Or if foo returns void, use
std::tie((foo(std::get<I>(ts)), 1) ... );
Note: On C++14 make_index_sequence is already defined (http://en.cppreference.com/w/cpp/utility/integer_sequence).
If you do need a left-to-right evaluation order, consider something like this:
template <typename T, typename ...R>
void do_foo_iter(T t, R ...r) {
foo(t);
do_foo(r...);
}
void do_foo_iter() {}
template<typename ...T, size_t ...I>
void do_foo_helper(std::tuple<T...> &ts, index_sequence<I...>) {
do_foo_iter(std::get<I>(ts) ...);
}
template <typename ...T>
void do_foo(std::tuple<T...> &ts) {
do_foo_helper(ts, make_index_sequence<sizeof...(T)>());
}
If you want to use std::tuple and you have C++ compiler which supports variadic templates, try code bellow (tested with g++4.5). This should be the answer to your question.
#include <tuple>
// ------------- UTILITY---------------
template<int...> struct index_tuple{};
template<int I, typename IndexTuple, typename... Types>
struct make_indexes_impl;
template<int I, int... Indexes, typename T, typename ... Types>
struct make_indexes_impl<I, index_tuple<Indexes...>, T, Types...>
{
typedef typename make_indexes_impl<I + 1, index_tuple<Indexes..., I>, Types...>::type type;
};
template<int I, int... Indexes>
struct make_indexes_impl<I, index_tuple<Indexes...> >
{
typedef index_tuple<Indexes...> type;
};
template<typename ... Types>
struct make_indexes : make_indexes_impl<0, index_tuple<>, Types...>
{};
// ----------- FOR EACH -----------------
template<typename Func, typename Last>
void for_each_impl(Func&& f, Last&& last)
{
f(last);
}
template<typename Func, typename First, typename ... Rest>
void for_each_impl(Func&& f, First&& first, Rest&&...rest)
{
f(first);
for_each_impl( std::forward<Func>(f), rest...);
}
template<typename Func, int ... Indexes, typename ... Args>
void for_each_helper( Func&& f, index_tuple<Indexes...>, std::tuple<Args...>&& tup)
{
for_each_impl( std::forward<Func>(f), std::forward<Args>(std::get<Indexes>(tup))...);
}
template<typename Func, typename ... Args>
void for_each( std::tuple<Args...>& tup, Func&& f)
{
for_each_helper(std::forward<Func>(f),
typename make_indexes<Args...>::type(),
std::forward<std::tuple<Args...>>(tup) );
}
template<typename Func, typename ... Args>
void for_each( std::tuple<Args...>&& tup, Func&& f)
{
for_each_helper(std::forward<Func>(f),
typename make_indexes<Args...>::type(),
std::forward<std::tuple<Args...>>(tup) );
}
boost::fusion is another option, but it requires its own tuple type: boost::fusion::tuple. Lets better stick to the standard! Here is a test:
#include <iostream>
// ---------- FUNCTOR ----------
struct Functor
{
template<typename T>
void operator()(T& t) const { std::cout << t << std::endl; }
};
int main()
{
for_each( std::make_tuple(2, 0.6, 'c'), Functor() );
return 0;
}
the power of variadic templates!
In MSVC STL there's a _For_each_tuple_element function (not documented):
#include <tuple>
// ...
std::tuple<int, char, float> values{};
std::_For_each_tuple_element(values, [](auto&& value)
{
// process 'value'
});
Another option would be to implement iterators for tuples. This has the advantage that you can use a variety of algorithms provided by the standard library and range-based for loops. An elegant approach to this is explained here https://foonathan.net/2017/03/tuple-iterator/. The basic idea is to turn tuples into a range with begin() and end() methods to provide iterators. The iterator itself returns a std::variant<...> which can then be visited using std::visit.
Here some examples:
auto t = std::tuple{ 1, 2.f, 3.0 };
auto r = to_range(t);
for(auto v : r)
{
std::visit(unwrap([](auto& x)
{
x = 1;
}), v);
}
std::for_each(begin(r), end(r), [](auto v)
{
std::visit(unwrap([](auto& x)
{
x = 0;
}), v);
});
std::accumulate(begin(r), end(r), 0.0, [](auto acc, auto v)
{
return acc + std::visit(unwrap([](auto& x)
{
return static_cast<double>(x);
}), v);
});
std::for_each(begin(r), end(r), [](auto v)
{
std::visit(unwrap([](const auto& x)
{
std::cout << x << std::endl;
}), v);
});
std::for_each(begin(r), end(r), [](auto v)
{
std::visit(overload(
[](int x) { std::cout << "int" << std::endl; },
[](float x) { std::cout << "float" << std::endl; },
[](double x) { std::cout << "double" << std::endl; }), v);
});
My implementation (which is heavily based on the explanations in the link above):
#ifndef TUPLE_RANGE_H
#define TUPLE_RANGE_H
#include <utility>
#include <functional>
#include <variant>
#include <type_traits>
template<typename Accessor>
class tuple_iterator
{
public:
tuple_iterator(Accessor acc, const int idx)
: acc_(acc), index_(idx)
{
}
tuple_iterator operator++()
{
++index_;
return *this;
}
template<typename T>
bool operator ==(tuple_iterator<T> other)
{
return index_ == other.index();
}
template<typename T>
bool operator !=(tuple_iterator<T> other)
{
return index_ != other.index();
}
auto operator*() { return std::invoke(acc_, index_); }
[[nodiscard]] int index() const { return index_; }
private:
const Accessor acc_;
int index_;
};
template<bool IsConst, typename...Ts>
struct tuple_access
{
using tuple_type = std::tuple<Ts...>;
using tuple_ref = std::conditional_t<IsConst, const tuple_type&, tuple_type&>;
template<typename T>
using element_ref = std::conditional_t<IsConst,
std::reference_wrapper<const T>,
std::reference_wrapper<T>>;
using variant_type = std::variant<element_ref<Ts>...>;
using function_type = variant_type(*)(tuple_ref);
using table_type = std::array<function_type, sizeof...(Ts)>;
private:
template<size_t Index>
static constexpr function_type create_accessor()
{
return { [](tuple_ref t) -> variant_type
{
if constexpr (IsConst)
return std::cref(std::get<Index>(t));
else
return std::ref(std::get<Index>(t));
} };
}
template<size_t...Is>
static constexpr table_type create_table(std::index_sequence<Is...>)
{
return { create_accessor<Is>()... };
}
public:
static constexpr auto table = create_table(std::make_index_sequence<sizeof...(Ts)>{});
};
template<bool IsConst, typename...Ts>
class tuple_range
{
public:
using tuple_access_type = tuple_access<IsConst, Ts...>;
using tuple_ref = typename tuple_access_type::tuple_ref;
static constexpr auto tuple_size = sizeof...(Ts);
explicit tuple_range(tuple_ref tuple)
: tuple_(tuple)
{
}
[[nodiscard]] auto begin() const
{
return tuple_iterator{ create_accessor(), 0 };
}
[[nodiscard]] auto end() const
{
return tuple_iterator{ create_accessor(), tuple_size };
}
private:
tuple_ref tuple_;
auto create_accessor() const
{
return [this](int idx)
{
return std::invoke(tuple_access_type::table[idx], tuple_);
};
}
};
template<bool IsConst, typename...Ts>
auto begin(const tuple_range<IsConst, Ts...>& r)
{
return r.begin();
}
template<bool IsConst, typename...Ts>
auto end(const tuple_range<IsConst, Ts...>& r)
{
return r.end();
}
template <class ... Fs>
struct overload : Fs... {
explicit overload(Fs&&... fs) : Fs{ fs }... {}
using Fs::operator()...;
template<class T>
auto operator()(std::reference_wrapper<T> ref)
{
return (*this)(ref.get());
}
template<class T>
auto operator()(std::reference_wrapper<const T> ref)
{
return (*this)(ref.get());
}
};
template <class F>
struct unwrap : overload<F>
{
explicit unwrap(F&& f) : overload<F>{ std::forward<F>(f) } {}
using overload<F>::operator();
};
template<typename...Ts>
auto to_range(std::tuple<Ts...>& t)
{
return tuple_range<false, Ts...>{t};
}
template<typename...Ts>
auto to_range(const std::tuple<Ts...>& t)
{
return tuple_range<true, Ts...>{t};
}
#endif
Read-only access is also supported by passing a const std::tuple<>& to to_range().
Others have mentioned some well-designed third-party libraries that you may turn to. However, if you are using C++ without those third-party libraries, the following code may help.
namespace detail {
template <class Tuple, std::size_t I, class = void>
struct for_each_in_tuple_helper {
template <class UnaryFunction>
static void apply(Tuple&& tp, UnaryFunction& f) {
f(std::get<I>(std::forward<Tuple>(tp)));
for_each_in_tuple_helper<Tuple, I + 1u>::apply(std::forward<Tuple>(tp), f);
}
};
template <class Tuple, std::size_t I>
struct for_each_in_tuple_helper<Tuple, I, typename std::enable_if<
I == std::tuple_size<typename std::decay<Tuple>::type>::value>::type> {
template <class UnaryFunction>
static void apply(Tuple&&, UnaryFunction&) {}
};
} // namespace detail
template <class Tuple, class UnaryFunction>
UnaryFunction for_each_in_tuple(Tuple&& tp, UnaryFunction f) {
detail::for_each_in_tuple_helper<Tuple, 0u>
::apply(std::forward<Tuple>(tp), f);
return std::move(f);
}
Note: The code compiles with any compiler supporing C++11, and it keeps consistency with design of the standard library:
The tuple need not be std::tuple, and instead may be anything that supports std::get and std::tuple_size; in particular, std::array and std::pair may be used;
The tuple may be a reference type or cv-qualified;
It has similar behavior as std::for_each, and returns the input UnaryFunction;
For C++14 (or laster version) users, typename std::enable_if<T>::type and typename std::decay<T>::type could be replaced with their simplified version, std::enable_if_t<T> and std::decay_t<T>;
For C++17 (or laster version) users, std::tuple_size<T>::value could be replaced with its simplified version, std::tuple_size_v<T>.
For C++20 (or laster version) users, the SFINAE feature could be implemented with the Concepts.
Using constexpr and if constexpr(C++17) this is fairly simple and straight forward:
template <std::size_t I = 0, typename ... Ts>
void print(std::tuple<Ts...> tup) {
if constexpr (I == sizeof...(Ts)) {
return;
} else {
std::cout << std::get<I>(tup) << ' ';
print<I+1>(tup);
}
}
I might have missed this train, but this will be here for future reference.
Here's my construct based on this answer and on this gist:
#include <tuple>
#include <utility>
template<std::size_t N>
struct tuple_functor
{
template<typename T, typename F>
static void run(std::size_t i, T&& t, F&& f)
{
const std::size_t I = (N - 1);
switch(i)
{
case I:
std::forward<F>(f)(std::get<I>(std::forward<T>(t)));
break;
default:
tuple_functor<I>::run(i, std::forward<T>(t), std::forward<F>(f));
}
}
};
template<>
struct tuple_functor<0>
{
template<typename T, typename F>
static void run(std::size_t, T, F){}
};
You then use it as follow:
template<typename... T>
void logger(std::string format, T... args) //behaves like C#'s String.Format()
{
auto tp = std::forward_as_tuple(args...);
auto fc = [](const auto& t){std::cout << t;};
/* ... */
std::size_t some_index = ...
tuple_functor<sizeof...(T)>::run(some_index, tp, fc);
/* ... */
}
There could be room for improvements.
As per OP's code, it would become this:
const std::size_t num = sizeof...(T);
auto my_tuple = std::forward_as_tuple(t...);
auto do_sth = [](const auto& elem){/* ... */};
for(int i = 0; i < num; ++i)
tuple_functor<num>::run(i, my_tuple, do_sth);
Of all the answers I've seen here, here and here, I liked #sigidagi's way of iterating best. Unfortunately, his answer is very verbose which in my opinion obscures the inherent clarity.
This is my version of his solution which is more concise and works with std::tuple, std::pair and std::array.
template<typename UnaryFunction>
void invoke_with_arg(UnaryFunction)
{}
/**
* Invoke the unary function with each of the arguments in turn.
*/
template<typename UnaryFunction, typename Arg0, typename... Args>
void invoke_with_arg(UnaryFunction f, Arg0&& a0, Args&&... as)
{
f(std::forward<Arg0>(a0));
invoke_with_arg(std::move(f), std::forward<Args>(as)...);
}
template<typename Tuple, typename UnaryFunction, std::size_t... Indices>
void for_each_helper(Tuple&& t, UnaryFunction f, std::index_sequence<Indices...>)
{
using std::get;
invoke_with_arg(std::move(f), get<Indices>(std::forward<Tuple>(t))...);
}
/**
* Invoke the unary function for each of the elements of the tuple.
*/
template<typename Tuple, typename UnaryFunction>
void for_each(Tuple&& t, UnaryFunction f)
{
using size = std::tuple_size<typename std::remove_reference<Tuple>::type>;
for_each_helper(
std::forward<Tuple>(t),
std::move(f),
std::make_index_sequence<size::value>()
);
}
Demo: coliru
C++14's std::make_index_sequence can be implemented for C++11.
Expanding on #Stypox answer, we can make their solution more generic (C++17 onward). By adding a callable function argument:
template<size_t I = 0, typename... Tp, typename F>
void for_each_apply(std::tuple<Tp...>& t, F &&f) {
f(std::get<I>(t));
if constexpr(I+1 != sizeof...(Tp)) {
for_each_apply<I+1>(t, std::forward<F>(f));
}
}
Then, we need a strategy to visit each type.
Let start with some helpers (first two taken from cppreference):
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
template<class ... Ts> struct variant_ref { using type = std::variant<std::reference_wrapper<Ts>...>; };
variant_ref is used to allow tuples' state to be modified.
Usage:
std::tuple<Foo, Bar, Foo> tuples;
for_each_apply(tuples,
[](variant_ref<Foo, Bar>::type &&v) {
std::visit(overloaded {
[](Foo &arg) { arg.foo(); },
[](Bar const &arg) { arg.bar(); },
}, v);
});
Result:
Foo0
Bar
Foo0
Foo1
Bar
Foo1
For completeness, here are my Bar & Foo:
struct Foo {
void foo() {std::cout << "Foo" << i++ << std::endl;}
int i = 0;
};
struct Bar {
void bar() const {std::cout << "Bar" << std::endl;}
};
I have stumbled on the same problem for iterating over a tuple of function objects, so here is one more solution:
#include <tuple>
#include <iostream>
// Function objects
class A
{
public:
inline void operator()() const { std::cout << "A\n"; };
};
class B
{
public:
inline void operator()() const { std::cout << "B\n"; };
};
class C
{
public:
inline void operator()() const { std::cout << "C\n"; };
};
class D
{
public:
inline void operator()() const { std::cout << "D\n"; };
};
// Call iterator using recursion.
template<typename Fobjects, int N = 0>
struct call_functors
{
static void apply(Fobjects const& funcs)
{
std::get<N>(funcs)();
// Choose either the stopper or descend further,
// depending if N + 1 < size of the tuple.
using caller = std::conditional_t
<
N + 1 < std::tuple_size_v<Fobjects>,
call_functors<Fobjects, N + 1>,
call_functors<Fobjects, -1>
>;
caller::apply(funcs);
}
};
// Stopper.
template<typename Fobjects>
struct call_functors<Fobjects, -1>
{
static void apply(Fobjects const& funcs)
{
}
};
// Call dispatch function.
template<typename Fobjects>
void call(Fobjects const& funcs)
{
call_functors<Fobjects>::apply(funcs);
};
using namespace std;
int main()
{
using Tuple = tuple<A,B,C,D>;
Tuple functors = {A{}, B{}, C{}, D{}};
call(functors);
return 0;
}
Output:
A
B
C
D
There're many great answers, but for some reason most of them don't consider returning the results of applying f to our tuple...
or did I overlook it? Anyway, here's yet another way you can do that:
Doing Foreach with style (debatable)
auto t = std::make_tuple(1, "two", 3.f);
t | foreach([](auto v){ std::cout << v << " "; });
And returning from that:
auto t = std::make_tuple(1, "two", 3.f);
auto sizes = t | foreach([](auto v) {
return sizeof(v);
});
sizes | foreach([](auto v) {
std::cout << v;
});
Implementation (pretty simple one)
Edit: it gets a little messier.
I won't include some metaprogramming boilerplate here, for it will definitely make things less readable and besides, I believe those have already been answered somewhere on stackoverflow.
In case you're feeling lazy, feel free to peek into my github repo for implementation of both
#include <utility>
// Optional includes, if you don't want to implement it by hand or google it
// you can find it in the repo (link below)
#include "typesystem/typelist.hpp"
// used to check if all return types are void,
// making it a special case
// (and, alas, not using constexpr-if
// for the sake of being compatible with C++14...)
template <bool Cond, typename T, typename F>
using select = typename std::conditional<Cond, T, F>::type;
template <typename F>
struct elementwise_apply {
F f;
};
template <typename F>
constexpr auto foreach(F && f) -> elementwise_apply<F> { return {std::forward<F>(f)}; }
template <typename R>
struct tuple_map {
template <typename F, typename T, size_t... Is>
static constexpr decltype(auto) impl(std::index_sequence<Is...>, F && f, T&& tuple) {
return R{ std::forward<F>(f)( std::get<Is>(tuple) )... };
}
};
template<>
struct tuple_map<void> {
template <typename F, typename T, size_t... Is>
static constexpr void impl(std::index_sequence<Is...>, F && f, T&& tuple) {
[[maybe_unused]] std::initializer_list<int> _ {((void)std::forward<F>(f)( std::get<Is>(tuple) ), 0)... };
}
};
template <typename F, typename... Ts>
constexpr decltype(auto) operator| (std::tuple<Ts...> & t, fmap<F> && op) {
constexpr bool all_void = core::Types<decltype( std::move(op).f(std::declval<Ts&>()) )...>.all( core::is_void );
using R = meta::select<all_void, void, std::tuple<decltype(std::move(op).f(std::declval<Ts&>()))...>>;
return tuple_map<R>::impl(std::make_index_sequence<sizeof...(Ts)>{}, std::move(op).f, t);
}
template <typename F, typename... Ts>
constexpr decltype(auto) operator| (std::tuple<Ts...> const& t, fmap<F> && op) {
constexpr bool all_void = check if all "decltype( std::move(op).f(std::declval<Ts>()) )..." types are void, since then it's a special case
// e.g. core::Types<decltype( std::move(op).f(std::declval<Ts>()) )...>.all( core::is_void );
using R = meta::select<all_void, void, std::tuple<decltype(std::move(op).f(std::declval<Ts const&>()))...>>;
return tuple_map<R>::impl(std::make_index_sequence<sizeof...(Ts)>{}, std::move(op).f, t);
}
template <typename F, typename... Ts>
constexpr decltype(auto) operator| (std::tuple<Ts...> && t, fmap<F> && op) {
constexpr bool all_void = core::Types<decltype( std::move(op).f(std::declval<Ts&&>()) )...>.all( core::is_void );
using R = meta::select<all_void, void, std::tuple<decltype(std::move(op).f(std::declval<Ts&&>()))...>>;
return tuple_map<R>::impl(std::make_index_sequence<sizeof...(Ts)>{}, std::move(op).f, std::move(t));
}
Yeah, that would be much nicer if we were to use C++17
This is also an example of std::moving object's members, for which I'll better refer to this nice brief article
P.S. If you're stuck checking if all "decltype( std::move(op).f(std::declval()) )..." types are void
you can find some metaprogramming library, or, if those libraries seem too hard to grasp (which some of them may be due to some crazy metaprogramming tricks), you know where to look
template <typename F, typename T>
static constexpr size_t
foreach_in_tuple(std::tuple<T> & tuple, F && do_, size_t index_ = 0)
{
do_(tuple, index_);
return index_;
}
template <typename F, typename T, typename U, typename... Types>
static constexpr size_t
foreach_in_tuple(std::tuple<T,U,Types...> & tuple, F && do_, size_t index_ = 0)
{
if(!do_(tuple, index_))
return index_;
auto & next_tuple = reinterpret_cast<std::tuple<U,Types...> &>(tuple);
return foreach_in_tuple(next_tuple, std::forward<F>(do_), index_+1);
}
int main()
{
using namespace std;
auto tup = make_tuple(1, 2.3f, 'G', "hello");
foreach_in_tuple(tup, [](auto & tuple, size_t i)
{
auto & value = std::get<0>(tuple);
std::cout << i << " " << value << std::endl;
// if(i >= 2) return false; // break;
return true; // continue
});
}
Here is a solution based on std::interger_sequence.
As I don't know if my_tuple is constructed from std::make_tuple<T>(T &&...) in your code. It's essential for how to construct std::integer_sequence in the solution below.
(1) if your already have a my_tuple outside your function(not using template<typename ...T>), You can use
[](auto my_tuple)
{
[&my_tuple]<typename N, N... n>(std::integer_sequence<N, n...> int_seq)
{
((std::cout << std::get<n>(my_tuple) << '\n'), ...);
}(std::make_index_sequence<std::tuple_size_v<decltype(my_tuple)>>{});
}(std::make_tuple());
(2) if your havn't constructed my_tuple in your function and want to handle your T ...arguments
[]<typename ...T>(T... args)
{
[&args...]<typename N, N... n>(std::integer_sequence<N, n...> int_seq)
{
((std::cout << std::get<n>(std::forward_as_tuple(args...)) << '\n'), ...);
}(std::index_sequence_for<T...>{});
}();
boost's tuple provides helper functions get_head() and get_tail() so your helper functions may look like this:
inline void call_do_sth(const null_type&) {};
template <class H, class T>
inline void call_do_sth(cons<H, T>& x) { x.get_head().do_sth(); call_do_sth(x.get_tail()); }
as described in here http://www.boost.org/doc/libs/1_34_0/libs/tuple/doc/tuple_advanced_interface.html
with std::tuple it should be similar.
Actually, unfortunately std::tuple does not seem to provide such interface, so methods suggested before should work, or you would need to switch to boost::tuple which has other benefits (like io operators already provided). Though there is downside of boost::tuple with gcc - it does not accept variadic templates yet, but that may be already fixed as I do not have latest version of boost installed on my machine.