-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathArray.h
119 lines (98 loc) · 4.27 KB
/
Array.h
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
/**
* ai-utils -- C++ Core utilities
*
* @file
* @brief Definition of template classes ArrayIndex and Array in namespace utils.
*
* @Copyright (C) 2018 Carlo Wood.
*
* pub dsa3072/C155A4EEE4E527A2 2018-08-16 Carlo Wood (CarloWood on Libera) <carlo@alinoe.com>
* fingerprint: 8020 B266 6305 EE2F D53E 6827 C155 A4EE E4E5 27A2
*
* This file is part of ai-utils.
*
* ai-utils is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ai-utils is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ai-utils. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <array>
#include <iostream>
#include "debug.h"
namespace utils {
template <typename Category>
class ArrayIndex;
template<typename Category>
std::ostream& operator<<(std::ostream& os, ArrayIndex<Category> const& index);
template <typename Category>
class ArrayIndex
{
private:
int m_value;
public:
constexpr ArrayIndex() : m_value(-1) { }
explicit constexpr ArrayIndex(int value) : m_value(value) { }
constexpr int get_value() const { return m_value; }
explicit constexpr operator std::size_t() const { return m_value; }
ArrayIndex& operator++() { ++m_value; return *this; }
ArrayIndex operator++(int) { ArrayIndex old(m_value); ++m_value; return old; }
ArrayIndex& operator--() { --m_value; return *this; }
ArrayIndex operator--(int) { ArrayIndex old(m_value); --m_value; return old; }
void set_to_zero() { m_value = 0; }
bool is_zero() const { return m_value == 0; }
void set_to_undefined() { m_value = -1; }
bool undefined() const { return m_value == -1; }
constexpr bool operator==(ArrayIndex const& index) const { return m_value == index.m_value; }
constexpr bool operator!=(ArrayIndex const& index) const { return m_value != index.m_value; }
constexpr bool operator<(ArrayIndex const& index) const { return m_value < index.m_value; }
constexpr bool operator>(ArrayIndex const& index) const { return m_value > index.m_value; }
constexpr bool operator<=(ArrayIndex const& index) const { return m_value <= index.m_value; }
constexpr bool operator>=(ArrayIndex const& index) const { return m_value >= index.m_value; }
ArrayIndex operator-(int n) const { return ArrayIndex{m_value - n}; }
ArrayIndex operator+(int n) const { return ArrayIndex{m_value + n}; }
friend std::ostream& operator<<<>(std::ostream& os, ArrayIndex<Category> const& index);
};
template<typename Category>
std::ostream& operator<<(std::ostream& os, ArrayIndex<Category> const& index)
{
os << '#' << index.m_value;
return os;
}
template<typename T, std::size_t N, typename _Index = ArrayIndex<T>>
class Array : public std::array<T, N>
{
protected:
using _Base = std::array<T, N>;
template <std::size_t... Is>
constexpr Array(std::initializer_list<T> ilist, std::index_sequence<Is...>) : std::array<T, N>{T{*(ilist.begin() + Is)}...}
{
}
public:
using reference = typename _Base::reference;
using const_reference = typename _Base::const_reference;
using index_type = _Index;
Array() = default;
constexpr Array(std::initializer_list<T> ilist) : Array(ilist, std::make_index_sequence<N>{})
{
// The number of arguments must be equal the size of the array, because
// each is accessed in the above constructor. Unfortunately we can't pass
// std::make_index_sequence<ilist.size()>{}.
ASSERT(ilist.size() == N);
}
reference operator[](index_type __n) _GLIBCXX_NOEXCEPT { return _Base::operator[](static_cast<size_t>(__n)); }
const_reference operator[](index_type __n) const _GLIBCXX_NOEXCEPT { return _Base::operator[](static_cast<size_t>(__n)); }
reference at(index_type __n) { return _Base::at(static_cast<size_t>(__n)); }
const_reference at(index_type __n) const { return _Base::at(static_cast<size_t>(__n)); }
index_type ibegin() const { return index_type(0); }
index_type iend() const { return index_type((int)N); }
};
} // namespace utils