1/*
2 * LegacyClonk
3 *
4 * Copyright (c) 2020-2021, The LegacyClonk Team and contributors
5 *
6 * Distributed under the terms of the ISC license; see accompanying file
7 * "COPYING" for details.
8 *
9 * "Clonk" is a registered trademark of Matthes Bender, used with permission.
10 * See accompanying file "TRADEMARK" for details.
11 *
12 * To redistribute this file separately, substitute the full license texts
13 * for the above references.
14 */
15
16#pragma once
17
18#include <concepts>
19#include <functional>
20#include <limits>
21#include <memory>
22#include <stdexcept>
23#include <type_traits>
24#include <utility>
25
26template<std::integral To, std::integral From>
27To checked_cast(From from)
28{
29 if constexpr (std::is_signed_v<From>)
30 {
31 if constexpr (std::is_unsigned_v<To>)
32 {
33 if (from < 0)
34 {
35 throw std::runtime_error{"Conversion of negative value to unsigned type requested"};
36 }
37 }
38 else if constexpr (std::numeric_limits<From>::min() < std::numeric_limits<To>::min())
39 {
40 if (from < std::numeric_limits<To>::min())
41 {
42 throw std::runtime_error{"Conversion of value requested that is smaller than the target-type minimum"};
43 }
44 }
45 }
46
47 if constexpr (std::numeric_limits<From>::max() > std::numeric_limits<To>::max())
48 {
49 if (std::cmp_greater(from, std::numeric_limits<To>::max()))
50 {
51 throw std::runtime_error{"Conversion of value requested that is bigger than the target-type maximum"};
52 }
53 }
54
55 return static_cast<To>(from);
56}
57
58template<typename... T>
59class StdOverloadedCallable : public T...
60{
61public:
62 StdOverloadedCallable(T... bases) : T{bases}... {}
63 using T::operator()...;
64};
65
66namespace detail
67{
68 template <typename Function>
69 struct FunctionSingleArgument_s;
70
71 template <typename Return, typename Argument>
72 struct FunctionSingleArgument_s<Return(*)(Argument)>
73 {
74 using type = Argument;
75 };
76
77 template <auto function>
78 using FunctionSingleArgument = typename FunctionSingleArgument_s<decltype(function)>::type;
79}
80
81template <auto function>
82struct C4SingleArgumentFunctionFunctor
83{
84 using Arg = detail::FunctionSingleArgument<function>;
85
86 void operator()(Arg arg)
87 {
88 std::invoke(function, std::forward<Arg>(arg));
89 }
90};
91
92template <auto free>
93using C4DeleterFunctionUniquePtr = std::unique_ptr<std::remove_pointer_t<detail::FunctionSingleArgument<free>>, C4SingleArgumentFunctionFunctor<free>>;
94