summaryrefslogtreecommitdiff
path: root/modules/core/c++/abstract/common.hpp
blob: 408946c6455d8b8df07ab5414d26f2af8ef143eb (plain)
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#pragma once

#include <cstdint>
#include <memory>
#include <optional>
#include <utility>

namespace saw {

#define KEL_CONCAT_(x, y) x##y
#define KEL_CONCAT(x, y) KEL_CONCAT_(x, y)
#define KEL_UNIQUE_NAME(prefix) KEL_CONCAT(prefix, __LINE__)

#define KEL_FORBID_COPY(classname)                                             \
	classname(const classname &) = delete;                                     \
	classname &operator=(const classname &) = delete

#define KEL_FORBID_MOVE(classname)                                             \
	classname(classname &&) = delete;                                          \
	classname &operator=(classname &&) = delete

#define KEL_DEFAULT_COPY(classname)                                            \
	classname(const classname &) = default;                                    \
	classname &operator=(const classname &) = default

#define KEL_DEFAULT_MOVE(classname)                                            \
	classname(classname &&) = default;                                         \
	classname &operator=(classname &&) = default

// In case of C++20
#define KEL_ASSERT(expression)                                                 \
	assert(expression);                                                        \
	if (!(expression)) [[unlikely]]

template <typename T> using maybe = std::optional<T>;

template <typename T> using own = std::unique_ptr<T>;

template <typename T> using our = std::shared_ptr<T>;

template <typename T> using lent = std::weak_ptr<T>;

template<typename T>
class ptr {
private:
	T* ptr_;

public:
	ptr():
		ptr_{nullptr}
	{}

	ptr(T& ptr__):
		ptr_{&ptr__}
	{}

	KEL_DEFAULT_COPY(ptr);
	KEL_DEFAULT_MOVE(ptr);

	T& operator()(){
		return *ptr_;
	}

	const T& operator()() const {
		return *ptr_;
	}

	bool is_valid() const {
		return ptr_ != nullptr;
	}
};

/**
 * Reference class for easier distinction
 * of references and its referenced types.
 */
template <typename T>
class ref {
private:
	/**
	 * Referenced type
	 */
	T* ref_;

	/**
	 * We don't want to move since the would invalidate the type.
	 */
	KEL_FORBID_MOVE(ref);
public:
	/**
	 * Main constructor.
	 */
	constexpr ref(T& ref__):
		ref_{&ref__}
	{}

	KEL_DEFAULT_COPY(ref);

	/**
	 * Operator retrieving the itself.
	 */
	constexpr T& operator()(){
		return *ref_;
	}

	/**
	 * Operator retrieving the itself.
	 */
	constexpr const T& operator()() const {
		return *ref_;
	}
};

template <typename T, class... Args> own<T> heap(Args &&...args) {
	return own<T>(new T(std::forward<Args>(args)...));
}

template <typename T, class... Args> our<T> share(Args &&...args) {
	return std::make_shared<T>(std::forward<Args>(args)...);
}

template <typename T> T instance() noexcept;

template <typename Func, typename T> struct return_type_helper {
	typedef decltype(instance<Func>()(instance<T>())) Type;
};
template <typename Func> struct return_type_helper<Func, void> {
	typedef decltype(instance<Func>()()) Type;
};

template <typename Func, typename T>
using return_type = typename return_type_helper<Func, T>::Type;

/**
 * Struct describing a void type
 */
struct void_t {};

/**
 * Helper function since changing returns between void_t{} and make_error<...>() is a bit annoying.
 */
void_t make_void();

template <typename T> struct void_fix { typedef T Type; };
template <> struct void_fix<void> { typedef void_t Type; };
template <typename T> using fix_void = typename void_fix<T>::Type;

template <typename T> struct void_unfix { typedef T Type; };
template <> struct void_unfix<void_t> { typedef void Type; };
template <typename T> using unfix_void = typename void_unfix<T>::Type;

template <typename... T> constexpr bool always_false = false;

} // namespace saw