在编译时完全枚举 D 维数组的索引
Completely enumerate indices of D-dimensional array at compile time
为了测试一些多维结构,需要生成编译时多维索引以完全涵盖所有可能的情况。
我寻找编译时廉价的方式来实现上述目的。
我目前在做什么:
#include <type_traits>
#include <utility>
template< typename F, std::size_t ...indices >
struct enumerator;
template< typename F >
struct enumerator< F >
{
constexpr
enumerator(F && _f)
: f(std::forward< F >(_f))
{ ; }
template< std::size_t ...I >
constexpr
bool
operator () () const
{
return f(std::index_sequence< I... >{});
}
private :
F f;
};
template< typename F, std::size_t first, std::size_t ...rest >
struct enumerator< F, first, rest... >
: enumerator< F, rest... >
{
constexpr
enumerator(F && _f)
: enumerator< F, rest... >(std::forward< F >(_f))
{ ; }
template< std::size_t ...I >
constexpr
bool
operator () () const
{
return enumerator::template operator () < I... >(std::make_index_sequence< first >{}); // ltr
}
template< std::size_t ...I, std::size_t ...J >
constexpr
bool
operator () (std::index_sequence< J... >) const
{
return (enumerator< F, rest... >::template operator () < I..., J >() && ...); // rtl, `< J, I... >` - ltr
}
};
template< std::size_t ...I, typename F >
constexpr
enumerator< F, I... >
make_enumerator(F && f)
{
static_assert(0 < sizeof...(I));
static_assert(((0 < I) && ...));
return std::forward< F >(f);
}
// main.cpp
#include <iostream>
#include <cstdlib>
#include <cassert>
struct truth
{
template< std::size_t ...I >
constexpr
bool
operator () (std::index_sequence< I... >) const
{
return true;
}
};
struct printer
{
template< std::size_t ...I >
bool
operator () (std::index_sequence< I... >) const
{
for (std::size_t const & i : {I...}) {
std::cout << i << ' ';
}
std::cout << std::endl;
return true;
}
};
int
main()
{
static_assert(make_enumerator< 10, 10, 10, 10 >(truth{})());
assert((make_enumerator< 3, 3, 3 >(printer{})()));
return EXIT_SUCCESS;
}
对于 104 生成的案例,它消耗大约 10 秒的处理器时间。如何改进解决方案,或者有没有更好的方法来实现目标?
至于运行时,我会线性索引并做一个to_multi_index
,如下所示:
// Is0 * Is1 * ... * Isn, So in C++17 (Is * ... * 1u)
template <std::size_t ... Is>
struct accum_mul;
template <>
struct accum_mul<> : std::integral_constant<std::size_t, 1u>{};
template <std::size_t I, std::size_t ... Is>
struct accum_mul<I, Is...> :
std::integral_constant<std::size_t, I * accum_mul<Is...>::value>{};
template <typename Seq, typename Res = std::tuple<>>
struct coeff;
template <typename Res>
struct coeff<std::index_sequence<>, Res> {
using type = Res;
};
template <std::size_t I, std::size_t ... Is, typename ... TRes>
struct coeff<std::index_sequence<I, Is...>,
std::tuple<TRes...>>
: coeff<std::index_sequence<Is...>,
std::tuple<TRes..., accum_mul<Is...>>> {};
template <std::size_t I, typename coeffs, typename dims, typename Seq>
struct to_multi_index;
template <std::size_t I, typename coeffs, typename dims, std::size_t... Is>
struct to_multi_index<I, coeffs, dims, std::index_sequence<Is...>>
{
using type = std::index_sequence<(I / (std::tuple_element<Is, coeffs>::type::value)
% (std::tuple_element<Is, dims>::type::value))...>;
};
template <typename Indexes, typename coeffs, typename dims, typename dim_indexes>
struct to_multi_indexes;
template <std::size_t... Is, typename coeffs, typename dims, typename dim_indexes>
struct to_multi_indexes<std::index_sequence<Is...>, coeffs, dims, dim_indexes>
{
using type = std::tuple<typename to_multi_index<Is, coeffs, dims, dim_indexes>::type...>;
};
template <std::size_t...Is>
struct all_indexes
{
private:
using as_seq = std::index_sequence<Is...>;
using as_tuple = std::tuple<std::integral_constant<std::size_t, Is>...>;
using dim_index = std::make_index_sequence<sizeof...(Is)>;
using coeffs = typename coeff<as_seq>::type;
using elem_count = accum_mul<Is...>;
using index_seq = std::make_index_sequence<elem_count::value>;
public:
using type = typename to_multi_indexes<index_seq, coeffs, as_tuple, dim_index>::type;
};
现场演示
相关文章:
- 数组索引的值没有增加
- 并行用于C++17中数组索引范围内的循环
- 数组索引重载错误
- 通过指针与数组引用扩展数组索引序列
- SIGSEGV, 分段错误. 而 printf() 数组索引的值
- 缓冲区溢出 - 数组索引越界(严重)
- 为什么C++数组索引值是有符号的,而不是围绕size_t类型构建的(或者我错了)
- 查找下一个具有真值C++的数组索引
- 在编译时自动生成用于稀疏数组索引的switch语句
- 在数组索引上引发异常
- C++ 将二维数组索引与条件语句中的函数值进行比较
- 平衡数组索引,同时从左和右对数组求和
- 为什么C ,Devstudio,数组索引工作
- 如何对同一数组索引下的结构成员进行排序?
- 我想返回数组索引,而不是数组值
- C++相当于 Python 的:用于数组索引
- 分段错误:为什么这里的数组索引越界了
- 数组索引在地图上不是整数
- 根据用户输入的每个字母添加到数组索引
- C 数组索引