您可以通过生成一系列调用来避免递归std::get<Is>(t)...
函数,与Is
指数范围为begin
up to end-1
。生成从给定索引开始的连续数字序列相当容易,因为它足以使起点成为一个偏移量,然后将其添加到常规索引序列的每个项目,例如:
std::get<begin + 0>(t), std::get<begin + 1>(t), ... std::get<begin + n>(t)
其中序列的长度等于序列之间的距离begin
and end
.
#include <tuple>
#include <type_traits>
#include <utility>
#include <cstddef>
#include <limits>
template <std::size_t begin, typename Tuple, typename F, std::size_t... Is>
void for_each(Tuple&& t, F&& f, std::index_sequence<Is...>)
{
using expand = int[];
static_cast<void>(expand{ 0, (f(std::get<begin + Is>(std::forward<Tuple>(t))), void(), 0)... });
}
template <std::size_t begin = 0U, std::size_t end = std::numeric_limits<std::size_t>::max(), typename Tuple, typename F>
void for_each(Tuple&& t, F&& f)
{
for_each<begin>(std::forward<Tuple>(t), std::forward<F>(f)
, std::make_index_sequence<(end==std::numeric_limits<std::size_t>::max()?std::tuple_size<std::decay_t<Tuple>>::value:end)-begin>{});
}
Test:
int main()
{
auto t = std::make_tuple(3.14, "Hello World!", -1);
auto f = [](const auto& i) { std::cout << i << ' '; };
for_each<1>(t, f);
for_each<1,3>(t, f);
for_each<0,2>(t, f);
}
DEMO
另请注意,函数模板的默认模板参数不必放置在模板参数列表的末尾,因此,您可以避免丑陋的情况decltype(t), decltype(f)
部分。这意味着end
不能默认为std::tuple_size<Tuple>::value
(since Tuple
追随end
),但此时您所需要的只是一些默认的幻数。