不是没有帮助代码。
#define RETURNS(...) \
noexcept(noexcept(__VA_ARGS__)) \
-> decltype(__VA_ARGS__) \
{ return __VA_ARGS__; }
template<std::size_t I>
using index_t = std::integral_constant<std::size_t, I>;
template<std::size_t...Is>
constexpr auto index_over( std::index_sequence<Is...> ) noexcept(true) {
return [](auto&& f)
RETURNS( decltype(f)(f)( index_t<Is>{}... ) );
}
template<std::size_t N>
constexpr auto index_upto( index_t<N> ={} ) noexcept(true) {
return index_over( std::make_index_sequence<N>{} );
}
template<class F>
constexpr auto foreacher( F&& f ) {
return [&f](auto&&...args) noexcept( noexcept(f(args))&&... ) {
((void)(f(args)),...);
};
}
那是我们的管道。
template<int T>
void foo() {
index_upto<T>()(
foreacher([](auto I){
std::cout << I << "\n";
})
);
}
一个编译时循环,每一步都有值。
或者我们可以隐藏细节:
template<std::size_t start, std::size_t length, std::size_t step=1, class F>
constexpr void for_each( F&& f, index_t<start> ={}, index_t<length> ={}, index_t<step> ={} ) {
index_upto<length/step>()(
foreacher([&](auto I){
f( index_t<(I*step)+start>{} );
})
);
}
那么我们会得到:
for_each<0, T>([](auto I) {
std::cout << I << "\n";
});
或者
for_each([](auto I) {
std::cout << I << "\n";
}, index_t<0>{}, index_t<T>{});
这可以通过用户定义的文字和模板变量进一步改进:
template<std::size_t I>
constexpr index_t<I> index{};
template<char...cs>
constexpr auto operator""_idx() {
return index< parse_value(cs...) >;
}
whereparse_value
是一个constexpr
函数,它接受一个序列char...
并产生它的无符号整数表示。