tupleの要素を走査する

Indexの数字を増やしながらvisitorを適用しつつ線形再帰する方法もあるけれど、index_tupleを用いて再帰深度を抑えてやる方が良い気がするのでそのように実装した。
tupleの状態を変更したい場合は参照で受け取って値を書き換える関数を渡すと良さそう。constexprにするなら、適用結果のtupleを返す関数にしてやればよい。ただし、tupleを返す実装にすると、適用する関数で戻り値が実際には不要な場合でもvoid型の値は作れないので何らかのダミーの値を返すようにしてやる必要がある。(適切な呼び分けをメタプログラミングで実現出来るような気もする)
引数の評価順序は普通は未定義であるがThe full-expressions in an initializer-clause are evaluated in the order in which they appear. の場合に限り規定されているので、これを用いて評価順序を保証する。中央のstatic_cast<void>(0)はfuncの戻り値型がoperator ,をオーバーロードしている場合を考慮してみたけれど、現実的にはそんなことは滅多になさそう。
[追記] アドバイスを頂いて、実装をinitializer_listを受ける関数の呼び出しに変更。

恐らく賢いコンパイラは警告を出すので、警告抑制のattributeを書いておくと良い気がする。

しかし、どうやら標準のtupleは線形オーダーで構築するようなので走査の再帰深度を抑える意味は無いかったかも…。
ということでwx257osn2さんの書いた対数オーダーで構築できるtuple(https://gist.github.com/wx257osn2/8051171)を使ってみた…けれどメモリ消費が激しく、そもそも数百要素もあるようなtupleの構築自体のコストが高過ぎて走査どころではなかった。まぁ先に述べたようにこの方針なら新しいtupleを作って返すようにも出来るので、その意味では有用性はあるかもしれない。

#include <tuple>
#include <iostream>
#include <type_traits>
#include <initializer_list>

template <std::size_t...>
struct index_tuple {};
 
namespace detail {
 
template <typename IndexTuple, std::size_t Next>
struct index_range_next;
template <std::size_t... Indices, std::size_t Next>
struct index_range_next<index_tuple<Indices...>, Next> {
 public:
  typedef index_tuple<Indices..., (Indices + Next)...> type;
};
 
template <typename IndexTuple, std::size_t Next, std::size_t Tail>
struct index_range_next2;
template <std::size_t... Indices, std::size_t Next, std::size_t Tail>
struct index_range_next2<index_tuple<Indices...>, Next, Tail> {
 public:
  typedef index_tuple<Indices..., (Indices + Next)..., Tail> type;
};
 
template <std::size_t First, std::size_t Step, std::size_t N,
          typename Enable = void>
struct index_range_impl;
template <std::size_t First, std::size_t Step, std::size_t N>
struct index_range_impl<First, Step, N,
                        typename std::enable_if<(N == 0)>::type> {
 public:
  typedef index_tuple<> type;
};
template <std::size_t First, std::size_t Step, std::size_t N>
struct index_range_impl<First, Step, N,
                        typename std::enable_if<(N == 1)>::type> {
 public:
  typedef index_tuple<First> type;
};
template <std::size_t First, std::size_t Step, std::size_t N>
struct index_range_impl<First, Step, N,
                        typename std::enable_if<(N > 1 && N % 2 == 0)>::
                            type> : public detail::
                                        index_range_next<
                                            typename detail::index_range_impl<
                                                First, Step, N / 2>::type,
                                            First + N / 2 * Step> {};
template <std::size_t First, std::size_t Step, std::size_t N>
struct index_range_impl<First, Step, N,
                        typename std::enable_if<(N > 1 && N % 2 == 1)>::
                            type> : public detail::
                                        index_range_next2<
                                            typename detail::index_range_impl<
                                                First, Step, N / 2>::type,
                                            First + N / 2 * Step,
                                            First + (N - 1) * Step> {};
 
template <std::size_t First, typename IndexTuple>
struct index_range_helper;
template <std::size_t First, std::size_t... Indices>
struct index_range_helper<First, index_tuple<Indices...>> {
 public:
  typedef index_tuple<(Indices + First)...> type;
};

inline void tuple_foreach_impl2(std::initializer_list<int>&&) {};
    
template <typename F, typename T, std::size_t... Indices>
void tuple_foreach_impl(F func, const T& t, const index_tuple<Indices...>&) {
    tuple_foreach_impl2({(func(std::get<Indices>(t)), static_cast<void>(0), 0)...});
}
    
}  // namespace detail
 
template <std::size_t First, std::size_t Last, std::size_t Step = 1>
struct index_range
    : public detail::index_range_helper<
          First, typename detail::index_range_impl<
                     0, Step, ((Last - First) + (Step - 1)) / Step>::type> {};

template <typename F, typename... Types>
void tuple_foreach(F func, const std::tuple<Types...>& t) {
    return detail::tuple_foreach_impl(func, t, typename index_range<0, sizeof...(Types)>::type());
}

struct show {
    template <typename T>
    void operator()(T arg) {
        std::cout << arg << std::endl;
    }
};

int main() {
    auto t = std::make_tuple("hello world", '!', 123); 
    tuple_foreach(show(), t);
}