The Battle for Wesnoth  1.19.14+dev
general.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2025
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 <functional>
20 #include <string>
21 
22 namespace utils
23 {
24 /**
25  * Equivalent to as @c std::is_same_v except both types are passed through std::decay first.
26  *
27  * @tparam T1 The first type to compare.
28  * @tparam T2 The second type to compare.
29  */
30 template<typename T1, typename T2>
31 inline constexpr bool decayed_is_same = std::is_same_v<std::decay_t<T1>, std::decay_t<T2>>;
32 
33 /**
34  * Workaround for the fact that static_assert(false) is invalid.
35  * See https://devblogs.microsoft.com/oldnewthing/20200311-00/?p=103553
36  */
37 template<typename>
38 inline constexpr bool dependent_false_v = false;
39 
40 template<typename Enum>
41 constexpr std::underlying_type_t<Enum> to_underlying(Enum e) noexcept
42 {
43  return static_cast<std::underlying_type_t<Enum>>(e);
44 }
45 
46 namespace detail
47 {
48 /**
49  * A struct that exists to implement a generic wrapper for std::find.
50  * Container should "look like" an STL container of Values.
51  */
52 template<typename Container, typename Value>
54 {
55  static bool eval(const Container& container, const Value& value)
56  {
57  typename Container::const_iterator end = container.end();
58  return std::find(container.begin(), end, value) != end;
59  }
60 };
61 
62 /**
63  * A struct that exists to implement a generic wrapper for the find()
64  * member of associative containers.
65  * Container should "look like" an STL associative container.
66  */
67 template<typename Container>
68 struct contains_impl<Container, typename Container::key_type>
69 {
70  static bool eval(const Container& container, const typename Container::key_type& value)
71  {
72  return container.find(value) != container.end();
73  }
74 };
75 
76 } // namespace detail
77 
78 /**
79  * Returns true iff @a value is found in @a container.
80  *
81  * This should work whenever Container "looks like" an STL container of Values.
82  * Normally this uses std::find(), but a simulated partial template specialization
83  * exists when Value is Container::key_type. In this case, Container is assumed
84  * an associative container, and the member function find() is used.
85  */
86 template<typename Container, typename Value>
87 inline bool contains(const Container& container, const Value& value)
88 {
89  return detail::contains_impl<Container, Value>::eval(container, value);
90 }
91 
92 /**
93  * Utility function for finding the type of thing caught with `catch(...)`.
94  * Not implemented for other compilers at this time.
95  *
96  * @return For the GCC/clang compilers, the unmangled name of an unknown exception that was caught.
97  */
98 std::string get_unknown_exception_type();
99 
100 /**
101  * Convenience wrapper for using std::remove_if on a container.
102  *
103  * @todo c++20 use C++20's std::erase_if instead. The C++20 function returns the number of elements
104  * removed; this one could do that but it seems unnecessary to add it unless something is using it.
105  */
106 template<typename Container, typename Predicate>
107 void erase_if(Container& container, const Predicate& predicate)
108 {
109  container.erase(std::remove_if(container.begin(), container.end(), predicate), container.end());
110 }
111 
112 /**
113  * Convenience wrapper for using std::remove on a container.
114  *
115  * @todo C++20: use std::erase
116  */
117 template<typename Container, typename Value>
118 std::size_t erase(Container& container, const Value& value)
119 {
120  auto iter = std::remove(container.begin(), container.end(), value);
121  auto num_removed = container.end() - iter;
122  container.erase(iter, container.end());
123  return num_removed;
124 }
125 
126 /**
127  * Convenience wrapper for using std::sort on a container.
128  *
129  * @todo C++20: use std::ranges::sort
130  */
131 template<typename Container, typename Predicate>
132 void sort_if(Container& container, const Predicate& predicate)
133 {
134  std::sort(container.begin(), container.end(), predicate);
135 }
136 
137 /**
138  * Convenience wrapper for using find on a container without needing to comare to end()
139  */
140 template<typename Container, typename Value>
141 auto* find(Container& container, const Value& value)
142 {
143  auto res = container.find(value);
144  return (res == container.end()) ? nullptr : &*res;
145 }
146 
147 /**
148  * Returns a vector whose elements are initialized from the given range.
149  *
150  * @todo C++23: use std::vector and co's from_range constructor
151  */
152 template<typename T, typename Range>
153 inline std::vector<T> from_range(Range&& range)
154 {
155  return std::vector<T>(range.begin(), range.end());
156 }
157 
158 /**
159  * Conveniences wrapper for range algorithms.
160  *
161  * @todo C++20: use std::ranges
162  */
163 namespace ranges
164 {
165 namespace implementation
166 {
167 struct identity
168 {
169  template<typename T>
170  constexpr T&& operator()(T&& t) const noexcept
171  {
172  return std::forward<T>(t);
173  }
174 };
175 
176 } // namespace implementation
177 
178 template<typename Container, typename Value, typename Projection = implementation::identity>
179 auto find(Container& container, const Value& value, const Projection& projection = {})
180 {
181  auto end = container.end();
182  for(auto iter = container.begin(); iter != end; ++iter) {
183  if(std::invoke(projection, *iter) == value) {
184  return iter;
185  }
186  }
187 
188  return end;
189 }
190 
191 } // namespace ranges
192 
193 } // namespace utils
double t
Definition: astarsearch.cpp:63
T end(const std::pair< T, T > &p)
void remove()
Removes a tip.
Definition: tooltip.cpp:94
Contains the implementation details for lexical_cast and shouldn't be used directly.
auto find(Container &container, const Value &value, const Projection &projection={})
Definition: general.hpp:179
constexpr bool decayed_is_same
Equivalent to as std::is_same_v except both types are passed through std::decay first.
Definition: general.hpp:31
std::size_t erase(Container &container, const Value &value)
Convenience wrapper for using std::remove on a container.
Definition: general.hpp:118
std::vector< T > from_range(Range &&range)
Returns a vector whose elements are initialized from the given range.
Definition: general.hpp:153
bool contains(const Container &container, const Value &value)
Returns true iff value is found in container.
Definition: general.hpp:87
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:107
constexpr bool dependent_false_v
Workaround for the fact that static_assert(false) is invalid.
Definition: general.hpp:38
void sort_if(Container &container, const Predicate &predicate)
Convenience wrapper for using std::sort on a container.
Definition: general.hpp:132
constexpr std::underlying_type_t< Enum > to_underlying(Enum e) noexcept
Definition: general.hpp:41
auto * find(Container &container, const Value &value)
Convenience wrapper for using find on a container without needing to comare to end()
Definition: general.hpp:141
static bool eval(const Container &container, const typename Container::key_type &value)
Definition: general.hpp:70
A struct that exists to implement a generic wrapper for std::find.
Definition: general.hpp:54
static bool eval(const Container &container, const Value &value)
Definition: general.hpp:55
constexpr T && operator()(T &&t) const noexcept
Definition: general.hpp:170
#define e