The Battle for Wesnoth  1.19.7+dev
general.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2024
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #pragma once
16 
17 #include <algorithm>
18 #include <cctype>
19 #include <string>
20 
21 namespace utils
22 {
23 /**
24  * Equivalent to as @c std::is_same_v except both types are passed through std::decay first.
25  *
26  * @tparam T1 The first type to compare.
27  * @tparam T2 The second type to compare.
28  */
29 template<typename T1, typename T2>
30 inline constexpr bool decayed_is_same = std::is_same_v<std::decay_t<T1>, std::decay_t<T2>>;
31 
32 /**
33  * Workaround for the fact that static_assert(false) is invalid.
34  * See https://devblogs.microsoft.com/oldnewthing/20200311-00/?p=103553
35  */
36 template<typename>
37 inline constexpr bool dependent_false_v = false;
38 
39 template<typename Enum>
40 constexpr std::underlying_type_t<Enum> to_underlying(Enum e) noexcept
41 {
42  return static_cast<std::underlying_type_t<Enum>>(e);
43 }
44 
45 namespace detail
46 {
47 /**
48  * A struct that exists to implement a generic wrapper for std::find.
49  * Container should "look like" an STL container of Values.
50  */
51 template<typename Container, typename Value>
53 {
54  static bool eval(const Container& container, const Value& value)
55  {
56  typename Container::const_iterator end = container.end();
57  return std::find(container.begin(), end, value) != end;
58  }
59 };
60 
61 /**
62  * A struct that exists to implement a generic wrapper for the find()
63  * member of associative containers.
64  * Container should "look like" an STL associative container.
65  */
66 template<typename Container>
67 struct contains_impl<Container, typename Container::key_type>
68 {
69  static bool eval(const Container& container, const typename Container::key_type& value)
70  {
71  return container.find(value) != container.end();
72  }
73 };
74 
75 } // namespace detail
76 
77 /**
78  * Returns true iff @a value is found in @a container.
79  *
80  * This should work whenever Container "looks like" an STL container of Values.
81  * Normally this uses std::find(), but a simulated partial template specialization
82  * exists when Value is Container::key_type. In this case, Container is assumed
83  * an associative container, and the member function find() is used.
84  */
85 template<typename Container, typename Value>
86 inline bool contains(const Container& container, const Value& value)
87 {
88  return detail::contains_impl<Container, Value>::eval(container, value);
89 }
90 
91 /**
92  * Utility function for finding the type of thing caught with `catch(...)`.
93  * Not implemented for other compilers at this time.
94  *
95  * @return For the GCC/clang compilers, the unmangled name of an unknown exception that was caught.
96  */
97 std::string get_unknown_exception_type();
98 
99 /**
100  * Convenience wrapper for using std::remove_if on a container.
101  *
102  * todoc++20 use C++20's std::erase_if instead. The C++20 function returns the number of elements
103  * removed; this one could do that but it seems unnecessary to add it unless something is using it.
104  */
105 template<typename Container, typename Predicate>
106 void erase_if(Container& container, const Predicate& predicate)
107 {
108  container.erase(std::remove_if(container.begin(), container.end(), predicate), container.end());
109 }
110 
111 /**
112  * Convenience wrapper for using std::remove on a container.
113  *
114  * @todo C++20: use std::erase
115  */
116 template<typename Container, typename Value>
117 std::size_t erase(Container& container, const Value& value)
118 {
119  auto iter = std::remove(container.begin(), container.end(), value);
120  auto num_removed = container.end() - iter;
121  container.erase(iter, container.end());
122  return num_removed;
123 }
124 
125 /**
126  * Convenience wrapper for using std::sort on a container.
127  *
128  */
129 template<typename Container, typename Predicate>
130 void sort_if(Container& container, const Predicate& predicate)
131 {
132  std::sort(container.begin(), container.end(), predicate);
133 }
134 
135 /**
136  * Convenience wrapper for using find on a container without needing to comare to end()
137  *
138  */
139 template<typename Container, typename Value>
140 auto* find(Container& container, const Value& value)
141 {
142  auto res = container.find(value);
143  return (res == container.end()) ? nullptr : &*res;
144 }
145 
146 } // namespace utils
void remove()
Removes a tip.
Definition: tooltip.cpp:94
constexpr bool decayed_is_same
Equivalent to as std::is_same_v except both types are passed through std::decay first.
Definition: general.hpp:30
std::size_t erase(Container &container, const Value &value)
Convenience wrapper for using std::remove on a container.
Definition: general.hpp:117
bool contains(const Container &container, const Value &value)
Returns true iff value is found in container.
Definition: general.hpp:86
std::string get_unknown_exception_type()
Utility function for finding the type of thing caught with catch(...).
Definition: general.cpp:23
void erase_if(Container &container, const Predicate &predicate)
Convenience wrapper for using std::remove_if on a container.
Definition: general.hpp:106
constexpr bool dependent_false_v
Workaround for the fact that static_assert(false) is invalid.
Definition: general.hpp:37
void sort_if(Container &container, const Predicate &predicate)
Convenience wrapper for using std::sort on a container.
Definition: general.hpp:130
constexpr std::underlying_type_t< Enum > to_underlying(Enum e) noexcept
Definition: general.hpp:40
auto * find(Container &container, const Value &value)
Convenience wrapper for using find on a container without needing to comare to end()
Definition: general.hpp:140
static bool eval(const Container &container, const typename Container::key_type &value)
Definition: general.hpp:69
A struct that exists to implement a generic wrapper for std::find.
Definition: general.hpp:53
static bool eval(const Container &container, const Value &value)
Definition: general.hpp:54
#define e