RESTinio
compiler_features.hpp
Go to the documentation of this file.
1 /*
2  * RESTinio
3  */
4 
5 /*!
6  * @file
7  * @brief Detection of compiler version and absence of various features.
8  *
9  * @since v.0.6.0
10  */
11 
12 #pragma once
13 
14 #include <utility>
15 
16 // Try to use __has_cpp_attribute if it is supported.
17 #if defined(__has_cpp_attribute)
18  // clang-4 and clang-5 produce warnings when [[nodiscard]]
19  // is used with -std=c++11 and -std=c++14.
20  #if __has_cpp_attribute(nodiscard) &&
21  !(defined(__clang__) && __cplusplus < 201703L)
22  #define RESTINIO_NODISCARD [[nodiscard]]
23  #endif
24 
25  #if __has_cpp_attribute(fallthrough) &&
26  !(defined(__clang__) && __cplusplus < 201703L)
27  #define RESTINIO_FALLTHROUGH [[fallthrough]]
28  #endif
29 #endif
30 
31 // Handle the result of __has_cpp_attribute.
32 #if !defined( RESTINIO_NODISCARD )
33  #define RESTINIO_NODISCARD
34 #endif
35 
36 #if !defined( RESTINIO_FALLTHROUGH )
37  #define RESTINIO_FALLTHROUGH
38 #endif
39 
40 /*!
41  * @brief A wrapper around static_assert for checking that an expression
42  * is noexcept and execution of that expression
43  *
44  * Usage example:
45  * @code
46  * some_class::~some_class() noexcept {
47  * // We should have a guarantee that this call doesn't throw.
48  * RESTINIO_ENSURE_NOEXCEPT_CALL(m_some_resouce.release());
49  * ...
50  * }
51  * @endcode
52  *
53  * @attention
54  * This macro is a part of RESTinio and is not intended to be uses as
55  * a part of public API. It can be changed or remove in some future version
56  * without any prior notice.
57  *
58  * @since v.0.6.0
59  */
60 #define RESTINIO_ENSURE_NOEXCEPT_CALL(expr)
61  static_assert(noexcept(expr), "this call is expected to be noexcept: " #expr);
62  expr
63 
64 /*!
65  * @brief A wrapper around static_assert for checking that an expression is
66  * noexcept
67  *
68  * Usage example:
69  * @code
70  * void remove_appropriate_items_at_front(some_container_t & cnt) noexcept {
71  * RESTINIO_STATIC_ASSERT_NOEXCEPT(cnt.empty());
72  * RESTINIO_STATIC_ASSERT_NOEXCEPT(cnt.front());
73  * RESTINIO_STATIC_ASSERT_NOEXCEPT(cnt.pop_front());
74  *
75  * while(!cnt.empty() && some_confitions(cnt.front()) {
76  * // We don't expect exceptions here.
77  * cnt.pop_front();
78  * }
79  * }
80  * @endcode
81  *
82  * @attention
83  * This macro is a part of RESTinio and is not intended to be uses as
84  * a part of public API. It can be changed or remove in some future version
85  * without any prior notice.
86  *
87  * @since v.0.6.0
88  */
89 #define RESTINIO_STATIC_ASSERT_NOEXCEPT(expr)
90  static_assert(noexcept(expr), #expr " is expected to be noexcept" )
91 
92 /*!
93  * @brief A wrapper around static_assert for checking that an expression is
94  * not noexcept.
95  *
96  * Usage example:
97  * @code
98  * some_class::~some_class() noexcept {
99  * // If that call throws then we have to use try-catch block.
100  * RESTINIO_STATIC_ASSERT_NOT_NOEXCEPT(m_some_resouce.release());
101  * try {
102  * m_some_resouce.release();
103  * }
104  * catch(...) {}
105  * ...
106  * }
107  * @endcode
108  *
109  * @attention
110  * This macro is a part of RESTinio and is not intended to be uses as
111  * a part of public API. It can be changed or remove in some future version
112  * without any prior notice.
113  *
114  * @since v.0.6.0
115  */
116 #define RESTINIO_STATIC_ASSERT_NOT_NOEXCEPT(expr)
117  static_assert(!noexcept(expr), #expr " is not expected to be noexcept" )
118 
119 namespace restinio
120 {
121 
123 {
124 
125 template< bool Condition >
126 struct static_if_impl;
127 
128 template<>
129 struct static_if_impl<true>
130 {
131  template<typename If_Part, typename Else_Part>
132  static decltype(auto)
133  call( If_Part && if_part, Else_Part && )
134  {
135  return if_part();
136  }
137 };
138 
139 template<>
140 struct static_if_impl<false>
141 {
142  template<typename If_Part, typename Else_Part>
143  static decltype(auto)
144  call( If_Part &&, Else_Part && else_part )
145  {
146  return else_part();
147  }
148 };
149 
150 } /* namespace static_if_details */
151 
152 //
153 // static_if_else
154 //
155 /*!
156  * @brief An emulation of if constexpr for C++14.
157  *
158  * Usage example:
159  * @code
160  * static_if_else< noexcept(some-expression) >(
161  * []() noexcept {
162  * ... // Some action that doesn't throw.
163  * },
164  * [] {
165  * try {
166  * ... // Some action that throws.
167  * }
168  * catch(...) {}
169  * });
170  * @endcode
171  *
172  * @since v.0.6.1.1
173  */
174 template< bool Condition, typename If_Part, typename Else_Part >
175 decltype(auto)
176 static_if_else( If_Part && if_part, Else_Part && else_part )
177 {
178  return static_if_details::static_if_impl<Condition>::call(
179  std::forward<If_Part>(if_part),
180  std::forward<Else_Part>(else_part) );
181 }
182 
183 } /* namespace restinio */
static decltype(auto) call(If_Part &&if_part, Else_Part &&)
static decltype(auto) call(If_Part &&, Else_Part &&else_part)
decltype(auto) static_if_else(If_Part &&if_part, Else_Part &&else_part)
An emulation of if constexpr for C++14.
std::enable_if< std::is_same< Parameter_Container, query_string_params_t >::value||std::is_same< Parameter_Container, router::route_params_t >::value, optional_t< Value_Type > >::type opt_value(const Parameter_Container &params, string_view_t key)
Gets the value of a parameter specified by key wrapped in optional_t<Value_Type> if parameter exists ...
Definition: value_or.hpp:64