1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
| #include <iostream>
#include <cstddef>
template<typename T>
using Invoke = typename T::type;
template<size_t...>
struct index_sequence {
using type = index_sequence;
};
template<typename S1, typename S2>
struct _concat_sequence;
template<size_t... I1, size_t... I2>
struct _concat_sequence<index_sequence<I1...>, index_sequence<I2...>>
: index_sequence<I1..., (sizeof...(I1) + I2)...> {};
template<typename S1, typename S2>
using concat_sequence = Invoke<_concat_sequence<S1, S2>>;
template<size_t Length>
struct _make_index_sequence;
template<size_t Length>
using make_index_sequence = Invoke<_make_index_sequence<Length>>;
template<size_t Length>
struct _make_index_sequence
: concat_sequence<make_index_sequence<Length/2>, make_index_sequence<Length - Length / 2>> {};
template<>
struct _make_index_sequence<0> : index_sequence<> {};
template<>
struct _make_index_sequence<1> : index_sequence<0> {};
template<size_t offset, typename S>
struct _make_offset;
template<size_t offset, size_t... I>
struct _make_offset<offset, index_sequence<I...>> : index_sequence<(I + offset)...> {};
template<size_t offset, typename S>
using make_offset = Invoke<_make_offset<offset, S>>;
template<typename ValueType, size_t Size>
class const_array {
ValueType data_[Size];
template<size_t SZ1, size_t SZ2>
constexpr const_array(const_array<ValueType, SZ1> first, ValueType second, const_array<ValueType, SZ2> third)
: const_array(first, second, third, make_index_sequence<SZ1>(), make_index_sequence<SZ2>()) {}
template<size_t... I1, size_t... I2>
constexpr const_array(const_array<ValueType, sizeof...(I1)> first, ValueType second, const_array<ValueType, sizeof...(I2)> third, index_sequence<I1...>, index_sequence<I2...>)
: data_{ first[I1]..., second, third[I2]... } {}
template<size_t... I>
constexpr const_array(const_array<ValueType, Size - 1> arr, ValueType value, index_sequence<I...>)
: data_{ arr[I]..., value } {}
constexpr const_array(const_array<ValueType, Size - 1> arr, ValueType value)
: const_array(arr, value, make_index_sequence<Size - 1>()) {}
template<size_t L1, size_t L2, size_t... I1, size_t... I2>
constexpr const_array(const_array<ValueType, L1> arr1,
const_array<ValueType, L2> arr2,
index_sequence<I1...>,
index_sequence<I2...>)
: data_{ arr1[I1]..., arr2[I2]... } {};
template<size_t... I>
constexpr const_array(ValueType (&arr)[Size], index_sequence<I...>)
: data_{ arr[I]... } {}
friend class const_array<ValueType, Size - 1>;
public:
// construct const_array from only one element
constexpr explicit const_array(ValueType value) : data_{ value } {}
constexpr explicit const_array(ValueType (&arr)[Size])
: const_array(arr, make_index_sequence<Size>()) {}
template<size_t length, size_t... I>
constexpr const_array(const_array<ValueType, length> rhs, index_sequence<I...>)
: data_{ rhs[I]... } {}
template<size_t L1, size_t L2>
constexpr const_array(const_array<ValueType, L1> arr1, const_array<ValueType, L2> arr2)
: const_array(arr1, arr2, make_index_sequence<L1>(), make_index_sequence<L2>()) {};
template<size_t length, size_t st = 0>
constexpr const_array<ValueType, length> sub_array() const {
return const_array<ValueType, length>(*this, make_offset<st, make_index_sequence<length>>());
}
template<size_t i>
constexpr const_array<ValueType, Size> set(ValueType value) const {
return const_array<ValueType, Size>(
sub_array<i>(), value, sub_array<Size - i - 1, i + 1>()
);
}
template<size_t length>
constexpr const_array<ValueType, Size + length> append(const_array<ValueType, length> rhs) const {
return const_array<ValueType, Size + length>(*this, rhs);
};
constexpr const_array<ValueType, Size + 1> append(ValueType value) const {
return const_array<ValueType, Size + 1>(*this, value);
}
constexpr ValueType operator[] (size_t i) const {
return data_[i];
}
constexpr size_t size() const {
return Size;
}
};
|