]>
Commit | Line | Data |
---|---|---|
1 | /////////////////////////////////////////////////////////////////////////////// | |
2 | // | |
3 | // Copyright (c) 2015 Microsoft Corporation. All rights reserved. | |
4 | // | |
5 | // This code is licensed under the MIT License (MIT). | |
6 | // | |
7 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
8 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
9 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
10 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
11 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
12 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
13 | // THE SOFTWARE. | |
14 | // | |
15 | /////////////////////////////////////////////////////////////////////////////// | |
16 | ||
17 | #ifndef GSL_UTIL_H | |
18 | #define GSL_UTIL_H | |
19 | ||
20 | #include <gsl/gsl_assert> // for Expects | |
21 | ||
22 | #include <array> | |
23 | #include <cstddef> // for ptrdiff_t, size_t | |
24 | #include <initializer_list> // for initializer_list | |
25 | #include <type_traits> // for is_signed, integral_constant | |
26 | #include <utility> // for exchange, forward | |
27 | ||
28 | #if defined(_MSC_VER) && !defined(__clang__) | |
29 | ||
30 | #pragma warning(push) | |
31 | #pragma warning(disable : 4127) // conditional expression is constant | |
32 | ||
33 | #endif // _MSC_VER | |
34 | ||
35 | #if defined(__cplusplus) && (__cplusplus >= 201703L) | |
36 | #define GSL_NODISCARD [[nodiscard]] | |
37 | #else | |
38 | #define GSL_NODISCARD | |
39 | #endif // defined(__cplusplus) && (__cplusplus >= 201703L) | |
40 | ||
41 | namespace gsl | |
42 | { | |
43 | // | |
44 | // GSL.util: utilities | |
45 | // | |
46 | ||
47 | // index type for all container indexes/subscripts/sizes | |
48 | using index = std::ptrdiff_t; | |
49 | ||
50 | // final_action allows you to ensure something gets run at the end of a scope | |
51 | template <class F> | |
52 | class final_action | |
53 | { | |
54 | public: | |
55 | static_assert(!std::is_reference<F>::value && !std::is_const<F>::value && !std::is_volatile<F>::value, "Final_action should store its callable by value"); | |
56 | ||
57 | explicit final_action(F f) noexcept : f_(std::move(f)) {} | |
58 | ||
59 | final_action(final_action&& other) noexcept : f_(std::move(other.f_)), invoke_(std::exchange(other.invoke_, false)) {} | |
60 | ||
61 | final_action(const final_action&) = delete; | |
62 | final_action& operator=(const final_action&) = delete; | |
63 | final_action& operator=(final_action&&) = delete; | |
64 | ||
65 | GSL_SUPPRESS(f.6) // NO-FORMAT: attribute // terminate if throws | |
66 | ~final_action() noexcept | |
67 | { | |
68 | if (invoke_) f_(); | |
69 | } | |
70 | ||
71 | private: | |
72 | F f_; | |
73 | bool invoke_{true}; | |
74 | }; | |
75 | ||
76 | // finally() - convenience function to generate a final_action | |
77 | template <class F> | |
78 | GSL_NODISCARD final_action<typename std::remove_cv<typename std::remove_reference<F>::type>::type> finally(F&& f) noexcept | |
79 | { | |
80 | return final_action<typename std::remove_cv<typename std::remove_reference<F>::type>::type>(std::forward<F>(f)); | |
81 | } | |
82 | ||
83 | // narrow_cast(): a searchable way to do narrowing casts of values | |
84 | template <class T, class U> | |
85 | GSL_SUPPRESS(type.1) // NO-FORMAT: attribute | |
86 | constexpr T narrow_cast(U&& u) noexcept | |
87 | { | |
88 | return static_cast<T>(std::forward<U>(u)); | |
89 | } | |
90 | ||
91 | // | |
92 | // at() - Bounds-checked way of accessing builtin arrays, std::array, std::vector | |
93 | // | |
94 | template <class T, std::size_t N> | |
95 | GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute | |
96 | GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute | |
97 | constexpr T& at(T (&arr)[N], const index i) | |
98 | { | |
99 | Expects(i >= 0 && i < narrow_cast<index>(N)); | |
100 | return arr[narrow_cast<std::size_t>(i)]; | |
101 | } | |
102 | ||
103 | template <class Cont> | |
104 | GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute | |
105 | GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute | |
106 | constexpr auto at(Cont& cont, const index i) -> decltype(cont[cont.size()]) | |
107 | { | |
108 | Expects(i >= 0 && i < narrow_cast<index>(cont.size())); | |
109 | using size_type = decltype(cont.size()); | |
110 | return cont[narrow_cast<size_type>(i)]; | |
111 | } | |
112 | ||
113 | template <class T> | |
114 | GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute | |
115 | constexpr T at(const std::initializer_list<T> cont, const index i) | |
116 | { | |
117 | Expects(i >= 0 && i < narrow_cast<index>(cont.size())); | |
118 | return *(cont.begin() + i); | |
119 | } | |
120 | ||
121 | } // namespace gsl | |
122 | ||
123 | #if defined(_MSC_VER) && !defined(__clang__) | |
124 | ||
125 | #pragma warning(pop) | |
126 | ||
127 | #endif // _MSC_VER | |
128 | ||
129 | #endif // GSL_UTIL_H |