halcheck 1.0
Loading...
Searching...
No Matches
atom.hpp
1#ifndef HALCHECK_LIB_ATOM_HPP
2#define HALCHECK_LIB_ATOM_HPP
3
22#include <halcheck/lib/type_traits.hpp>
23#include <halcheck/lib/variant.hpp>
24
25#include <algorithm>
26#include <cstddef>
27#include <cstdint>
28#include <functional>
29#include <string>
30#include <type_traits>
31#include <utility>
32
33namespace halcheck { namespace lib {
34
39class symbol {
40public:
41 using value_type = std::string;
42
53 explicit symbol(const std::string &);
54
59 explicit symbol(const char * = "");
60
69 inline std::size_t hash() const noexcept { return _data->second; }
70
78 template<typename T, HALCHECK_REQUIRE(std::is_constructible<T, const std::string &>())>
79 explicit operator T() const {
80 return T(_data->first);
81 }
82
83private:
92 friend bool operator==(const symbol &lhs, const symbol &rhs) { return lhs._data == rhs._data; }
93
101 friend bool operator!=(const symbol &lhs, const symbol &rhs) { return lhs._data != rhs._data; }
102
104};
105
110class number {
111public:
116
121 number() = default;
122
127 number(value_type value) // NOLINT: implicit conversion
128 : _value(value) {}
129
140 template<
141 typename T,
144 HALCHECK_REQUIRE(sizeof(T) >= sizeof(value_type))>
145 explicit operator T() const {
146 return _value;
147 }
148
158 template<
159 typename T,
162 explicit operator T() const {
163 return T(_value);
164 }
165
166private:
175 friend bool operator==(number lhs, number rhs) { return lhs._value == rhs._value; }
176
185 friend bool operator!=(number lhs, number rhs) { return lhs._value != rhs._value; }
186
187 value_type _value = 0;
188};
189
194using atom = lib::variant<lib::symbol, lib::number>;
195
196namespace literals {
197#if __cplusplus >= 201806L
198template<std::size_t N>
199struct char_array {
200 char data[N]; // NOLINT
201 [[nodiscard]] constexpr size_t size() const { return N - 1; }
202 constexpr char_array(const char (&init)[N]) { // NOLINT
203 std::copy_n(init, N, data);
204 }
205};
206
207template<literals::char_array Value>
208lib::symbol operator""_s() {
209 static lib::symbol output(std::string(Value.data, Value.size()));
210 return output;
211}
212#elif ((__cplusplus >= 201606L || defined(__clang__)) && defined(__GNUG__)) || defined(HALCHECK_DOXYGEN)
213#pragma clang diagnostic push
214#pragma clang diagnostic ignored "-Wgnu-string-literal-operator-template"
220template<typename T, T... Data>
221lib::symbol operator""_s() {
222 static_assert(std::is_same<T, char>(), "T should be char");
223 static lib::symbol output(std::string{Data...});
224 return output;
225}
226#pragma clang diagnostic pop
227#else
228inline lib::symbol operator""_s(const char *data, std::size_t size) { return lib::symbol(std::string(data, size)); }
229#endif
230} // namespace literals
231
232}} // namespace halcheck::lib
233
234namespace std {
235
240template<>
241struct hash<halcheck::lib::symbol> {
242 std::size_t operator()(halcheck::lib::symbol value) const noexcept { return value.hash(); }
243};
244
249template<>
250struct hash<halcheck::lib::number> {
251 std::size_t operator()(halcheck::lib::number value) const noexcept {
253 }
254};
255
256} // namespace std
257#endif
number()=default
Creates a number with zero as its underlying value.
number(value_type value)
Creates a number with the given underlying value.
Definition atom.hpp:127
friend bool operator!=(number lhs, number rhs)
Determines if two numbers are equal.
Definition atom.hpp:185
friend bool operator==(number lhs, number rhs)
Determines if two numbers are equal.
Definition atom.hpp:175
A number is conceptually a signed integer with constant time equality comparison and hashing.
Definition atom.hpp:110
std::int64_t value_type
The underlying integral type.
Definition atom.hpp:115
symbol(const std::string &)
Construct a new symbol from a std::string.
friend bool operator!=(const symbol &lhs, const symbol &rhs)
Determines if two symbols are not equal.
Definition atom.hpp:101
friend bool operator==(const symbol &lhs, const symbol &rhs)
Determines if two symbols are equal.
Definition atom.hpp:92
std::size_t hash() const noexcept
Gets a hash code for this symbol.
Definition atom.hpp:69
symbol(const char *="")
Construct a new symbol from a C string.
A symbol is conceptually a std::string with constant time equality comparison and hashing.
Definition atom.hpp:39
T copy_n(T... args)
lib::variant< lib::symbol, lib::number > atom
An atom is either a symbol or a number.
Definition atom.hpp:194
HALCHECK_INLINE_CONSTEXPR struct halcheck::lib::@25 size
Obtains the size of a range.
#define HALCHECK_REQUIRE(...)
Expands to a template argument that is only valid if the given argument evaluates to true.
Definition type_traits.hpp:24
STL namespace.
T operator()(T... args)