数组初始化编译时间 - Constexpr 序列
Array Initialisation Compile Time - Constexpr Sequence
我正在阅读关于 SO 的 问题。
这个问题本身不是很有趣,但我想知道它是否存在以及如何实现编译时解决方案。
关于第一个序列:
All numbers except the ones which can be divided by 3.
顺序应该是这样的:
[1, 2, 4, 5, 7, 8, 10, 11, 13, 14, ...]
通过归纳法,我找到了该序列的数学公式:
f(0) = 0;
f(x > 0) = floor[(3x - 1) / 2];
所以我实现了一个 C++ constexpr
函数,它生成序列中的第 i-th 个数字:
#include <type_traits>
template <typename T = std::size_t>
constexpr T generate_ith_number(const std::size_t index) {
static_assert(std::is_integral<T>::value, "T must to be an integral type");
if (index == 0) return 0;
return (3 * index - 1) / 2;
}
现在我想生成一个 "compile-time array/sequence" 来存储序列的前 N 个数字。
结构应该是这样的:
template <typename T, T... values>
struct sequence {};
template <typename T, std::size_t SIZE>
struct generate_sequence {}; // TODO: implement
问题(不止一个,但相互关联):
1) 如何实现那种integer_sequence
?
2) 是否可以在编译时从 integer_sequence
构建 std::array
?
1) How to implement that kind of integer_sequence
?
template <std::size_t... Is>
constexpr auto make_sequence_impl(std::index_sequence<Is...>)
{
return std::index_sequence<generate_ith_number(Is)...>{};
}
template <std::size_t N>
constexpr auto make_sequence()
{
return make_sequence_impl(std::make_index_sequence<N>{});
}
2) Is it possible to build an std::array
from that integer_sequence
at compile time?
template <std::size_t... Is>
constexpr auto make_array_from_sequence_impl(std::index_sequence<Is...>)
{
return std::array<std::size_t, sizeof...(Is)>{Is...};
}
template <typename Seq>
constexpr auto make_array_from_sequence(Seq)
{
return make_array_from_sequence_impl(Seq{});
}
用法:
int main()
{
constexpr auto arr = make_array_from_sequence(make_sequence<6>());
static_assert(arr[0] == 0);
static_assert(arr[1] == 1);
static_assert(arr[2] == 2);
static_assert(arr[3] == 4);
static_assert(arr[4] == 5);
static_assert(arr[5] == 7);
}
我正在阅读关于 SO 的
这个问题本身不是很有趣,但我想知道它是否存在以及如何实现编译时解决方案。
关于第一个序列:
All numbers except the ones which can be divided by 3.
顺序应该是这样的:
[1, 2, 4, 5, 7, 8, 10, 11, 13, 14, ...]
通过归纳法,我找到了该序列的数学公式:
f(0) = 0;
f(x > 0) = floor[(3x - 1) / 2];
所以我实现了一个 C++ constexpr
函数,它生成序列中的第 i-th 个数字:
#include <type_traits>
template <typename T = std::size_t>
constexpr T generate_ith_number(const std::size_t index) {
static_assert(std::is_integral<T>::value, "T must to be an integral type");
if (index == 0) return 0;
return (3 * index - 1) / 2;
}
现在我想生成一个 "compile-time array/sequence" 来存储序列的前 N 个数字。
结构应该是这样的:
template <typename T, T... values>
struct sequence {};
template <typename T, std::size_t SIZE>
struct generate_sequence {}; // TODO: implement
问题(不止一个,但相互关联):
1) 如何实现那种integer_sequence
?
2) 是否可以在编译时从 integer_sequence
构建 std::array
?
1) How to implement that kind of
integer_sequence
?
template <std::size_t... Is>
constexpr auto make_sequence_impl(std::index_sequence<Is...>)
{
return std::index_sequence<generate_ith_number(Is)...>{};
}
template <std::size_t N>
constexpr auto make_sequence()
{
return make_sequence_impl(std::make_index_sequence<N>{});
}
2) Is it possible to build an
std::array
from thatinteger_sequence
at compile time?
template <std::size_t... Is>
constexpr auto make_array_from_sequence_impl(std::index_sequence<Is...>)
{
return std::array<std::size_t, sizeof...(Is)>{Is...};
}
template <typename Seq>
constexpr auto make_array_from_sequence(Seq)
{
return make_array_from_sequence_impl(Seq{});
}
用法:
int main()
{
constexpr auto arr = make_array_from_sequence(make_sequence<6>());
static_assert(arr[0] == 0);
static_assert(arr[1] == 1);
static_assert(arr[2] == 2);
static_assert(arr[3] == 4);
static_assert(arr[4] == 5);
static_assert(arr[5] == 7);
}