1.10
meta.h
1/*
2 * Copyright (C) 2018 Microchip Technology Inc. All rights reserved.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6#ifndef EGT_DETAIL_META_H
7#define EGT_DETAIL_META_H
8
14#include <cmath>
15#include <cstdlib>
16#include <egt/detail/math.h>
17#include <functional>
18#include <memory>
19#include <string>
20#include <type_traits>
21#include <utility>
22
23#ifdef egt_likely
24# define egt_likely(x) __builtin_expect((x), 1)
25#endif
26
27#ifndef egt_unlikely
28# define egt_unlikely(x) __builtin_expect((x), 0)
29#endif
30
31#if defined _WIN32 || defined __CYGWIN__
32# define EGT_HELPER_DLL_IMPORT __declspec(dllimport)
33# define EGT_HELPER_DLL_EXPORT __declspec(dllexport)
34# define EGT_HELPER_DLL_LOCAL
35#else
36# if __GNUC__ >= 4
37# define EGT_HELPER_DLL_IMPORT __attribute__ ((visibility ("default")))
38# define EGT_HELPER_DLL_EXPORT __attribute__ ((visibility ("default")))
39# define EGT_HELPER_DLL_LOCAL __attribute__ ((visibility ("hidden")))
40# else
41# define EGT_HELPER_DLL_IMPORT
42# define EGT_HELPER_DLL_EXPORT
43# define EGT_HELPER_DLL_LOCAL
44# endif
45#endif
46
47// Now we use the generic helper definitions above to define EGT_API and EGT_LOCAL.
48// EGT_API is used for the public API symbols. It either DLL imports or DLL exports (or does nothing for static build)
49// EGT_LOCAL is used for non-api symbols.
50
51#ifndef EGT_STATIC
52# define EGT_DLL
53#endif
54
55#ifdef EGT_DLL // defined if EGT is compiled as a DLL
56# ifdef EGT_DLL_EXPORTS // defined if we are building the EGT DLL (instead of using it)
57# define EGT_API EGT_HELPER_DLL_EXPORT
58# else
59# define EGT_API EGT_HELPER_DLL_IMPORT
60# endif // EGT_DLL_EXPORTS
61# define EGT_LOCAL EGT_HELPER_DLL_LOCAL
62#else // EGT_DLL is not defined: this means EGT is a static lib.
63# define EGT_API
64# define EGT_LOCAL
65#endif // EGT_DLL
66
67#ifndef SWIG
68# define EGT_DEPRECATED [[deprecated]]
69# ifdef __has_cpp_attribute
70# define EGT_HAVE_ATTRIBUTE(x) __has_cpp_attribute(x)
71# else
72# define EGT_HAVE_ATTRIBUTE(x) 0
73# endif
74# if EGT_HAVE_ATTRIBUTE(nodiscard) && !defined(__clang__)
75# define EGT_NODISCARD [[nodiscard]]
76# elif EGT_HAVE_ATTRIBUTE(warn_unused_result)
77# define EGT_NODISCARD __attribute__((warn_unused_result))
78# else
79# define EGT_NODISCARD
80# endif
81#else
82# define EGT_DEPRECATED
83# define EGT_NODISCARD
84#endif
85
86namespace egt
87{
88inline namespace v1
89{
90namespace detail
91{
92
96template <typename T>
97void ignoreparam(T&&) // NOLINT(readability-named-parameter)
98{}
99
100#ifndef SWIG
105template <typename T>
107{
108 T& m_x;
109public:
113 explicit ReverseRange(T& x) : m_x(x) {}
114
116 EGT_NODISCARD auto begin() const -> decltype(this->m_x.rbegin())
117 {
118 return m_x.rbegin();
119 }
120
122 EGT_NODISCARD auto end() const -> decltype(this->m_x.rend())
123 {
124 return m_x.rend();
125 }
126};
127
138template <typename T>
140{
141 return ReverseRange<T>(x);
142}
143#endif
144
148template<class T>
149class EGT_API NonCopyable
150{
151public:
152 NonCopyable(const NonCopyable&) = delete;
154 NonCopyable(NonCopyable&&) noexcept = default;
155 NonCopyable& operator=(NonCopyable&&) noexcept = default;
156protected:
157 NonCopyable() = default;
158 ~NonCopyable() = default;
159};
160
169template <class T>
170constexpr bool rule_of_5()
171{
172 static_assert(std::is_destructible<T>::value, "must be destructible");
173 static_assert(std::is_copy_constructible<T>::value, "must be copy constructible");
174 static_assert(std::is_move_constructible<T>::value, "must be move constructible");
175 static_assert(std::is_copy_assignable<T>::value, "must be copy assignable");
176 static_assert(std::is_move_assignable<T>::value, "must be move assignable");
177
178 return std::is_destructible<T>::value && std::is_copy_constructible<T>::value
179 && std::is_move_constructible<T>::value && std::is_copy_assignable<T>::value
180 && std::is_move_assignable<T>::value;
181}
182
193template<class T>
194constexpr bool change_if_diff(T& old, const T& to)
195{
196 if (old != to)
197 {
198 old = to;
199 return true;
200 }
201
202 return false;
203}
204
209template<>
210constexpr bool change_if_diff(float& old, const float& to)
211{
212 if (!detail::float_equal(old, to))
213 {
214 old = to;
215 return true;
216 }
217
218 return false;
219}
220
225template<>
226constexpr bool change_if_diff(double& old, const double& to)
227{
228 if (!detail::float_equal(old, to))
229 {
230 old = to;
231 return true;
232 }
233
234 return false;
235}
236
243template<class T>
244struct EGT_API ScopeExit
245{
249 // NOLINTNEXTLINE(hicpp-explicit-conversions)
250 explicit ScopeExit(T&& f) noexcept
251 : m_f(std::move(f)),
252 m_active(true)
253 {}
254
258 // NOLINTNEXTLINE(hicpp-explicit-conversions)
259 explicit ScopeExit(const T& f) noexcept
260 : m_f(f),
261 m_active(true)
262 {}
263
265 ScopeExit(ScopeExit&& other) noexcept
266 : m_f(std::move(other.m_f)),
267 m_active(other.m_active)
268 {
269 other.m_active = false;
270 }
271
272 ScopeExit() = delete;
273 ScopeExit(const ScopeExit&) = delete;
274 ScopeExit& operator=(const ScopeExit&) = delete;
276
278 {
279 if (m_active)
280 m_f();
281 }
282
283protected:
288};
289
294template<class T>
296{
297 return ScopeExit<T>(std::forward<T>(f));
298}
299
305template<class T>
306constexpr T bit(T n)
307{
308 return 1u << n;
309}
310
311}
312}
313}
314
315#endif
Utility base class to make a derived class non-copy-able.
Definition meta.h:150
NonCopyable(const NonCopyable &)=delete
NonCopyable(NonCopyable &&) noexcept=default
NonCopyable & operator=(const NonCopyable &)=delete
Range class to work with C++11 range based for loops in a reverse order.
Definition meta.h:107
ReverseRange(T &x)
Definition meta.h:113
EGT_NODISCARD auto begin() const -> decltype(this->m_x.rbegin())
begin iterator
Definition meta.h:116
EGT_NODISCARD auto end() const -> decltype(this->m_x.rend())
end iterator
Definition meta.h:122
ReverseRange< T > reverse_iterate(T &x)
Reverse iterator to work with C++11 range based for loops in a reverse order.
Definition meta.h:139
constexpr bool change_if_diff(T &old, const T &to)
Utility to test and change a value if it is different.
Definition meta.h:194
constexpr T bit(T n)
Utility to create a bit mask for the specified bit.
Definition meta.h:306
void ignoreparam(T &&)
Utility function to safely ignore a parameter to a function.
Definition meta.h:97
ScopeExit< T > on_scope_exit(T &&f)
Helper to construct a ScopeExit with proper type deduction of the template parameter,...
Definition meta.h:295
EGT framework namespace.
Definition animation.h:24
Utility to run a callback when this object goes out of scope.
Definition meta.h:245
ScopeExit & operator=(ScopeExit &&)=delete
ScopeExit(const T &f) noexcept
Definition meta.h:259
ScopeExit(ScopeExit &&other) noexcept
Move constructor.
Definition meta.h:265
T m_f
Callback function.
Definition meta.h:285
~ScopeExit()
Definition meta.h:277
bool m_active
Used to manage move.
Definition meta.h:287
ScopeExit & operator=(const ScopeExit &)=delete
ScopeExit(const ScopeExit &)=delete
ScopeExit(T &&f) noexcept
Definition meta.h:250