Skip to content

Commit d17fd6b

Browse files
committed
add the construct, make_unique and make_shared, etc. functions
1 parent 044edc1 commit d17fd6b

8 files changed

Lines changed: 829 additions & 6 deletions

File tree

include/MGIS/Config-c.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,4 +107,40 @@ typedef size_t mgis_size_type;
107107
#define MGIS_EXPORT MGIS_VISIBILITY_EXPORT
108108
#endif /* */
109109

110+
/*!
111+
* \def MGIS_PP_JOIN
112+
* \brief this macro joins joins its two arguments together.
113+
*
114+
* This macro was taken from the boost library:
115+
* - http://boost.org/
116+
*
117+
* The following piece of macro magic joins the two
118+
* arguments together, even when one of the arguments is
119+
* itself a macro (see 16.3.1 in C++ standard). The key
120+
* is that macro expansion of macro arguments does not
121+
* occur in MGIS_PP_DO_JOIN2 but does in MGIS_PP_DO_JOIN.
122+
*/
123+
#define MGIS_PP_JOIN(X, Y) MGIS_PP_DO_JOIN(X, Y)
124+
125+
/*!
126+
* \def MGIS_PP_DO_JOIN
127+
* \brief An helper macro for MGIS_PP_JOIN
128+
* \see MGIS_PP_JOIN
129+
*/
130+
#define MGIS_PP_DO_JOIN(X, Y) MGIS_PP_DO_JOIN2(X, Y)
131+
132+
/*!
133+
* \def MGIS_PP_DO_JOIN2
134+
* \brief An helper macro for MGIS_PP_JOIN
135+
* \see MGIS_PP_JOIN
136+
*/
137+
#define MGIS_PP_DO_JOIN2(X, Y) X##Y
138+
139+
/*!
140+
* \brief macro defining a unique local variable name for a temporary variable
141+
* that it not meant to be seen by the end-user
142+
*/
143+
#define MGIS_TEMPORARY_VARIABLE(X) \
144+
MGIS_PP_JOIN(MGIS_PP_JOIN(MGIS_PP_JOIN(mgis_temporary_, X), _), __LINE__)
145+
110146
#endif /* LIB_MGIS_CONFIG_C_H */
Lines changed: 358 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,358 @@
1+
/*!
2+
* \file MGIS/Utilities/Construct.hxx
3+
* \brief This header declares utility functions to build objects handling any
4+
* exception thrown by a constructor \date 06/11/2022
5+
*/
6+
7+
#ifndef LIB_MGIS_UTILITIES_CONSTRUCT_HXX
8+
#define LIB_MGIS_UTILITIES_CONSTRUCT_HXX
9+
10+
#include <memory>
11+
#include <optional>
12+
#include <type_traits>
13+
#include "MGIS/Context.hxx"
14+
#include "MGIS/InvalidResult.hxx"
15+
16+
/*!
17+
* \def MGIS_CONSTRUCT(Type, e, ...)
18+
* \brief a simple wrapper around the `construct` function which handles the
19+
* declaration of the source location if needed
20+
*
21+
* \param[in] Type: type of the object built
22+
* \param[in, out] ctx: execution context
23+
*/
24+
#ifdef MGIS_USE_SOURCE_LOCATION_INFORMATION
25+
#define MGIS_CONSTRUCT(Type, e, ...) \
26+
::mgis::construct<Type>(e, std::source_location::current(), __VA_ARGS__)
27+
#else
28+
#define MGIS_CONSTRUCT(Type, e, ...) ::mgis::construct<Type>(e, __VA_ARGS__)
29+
#endif
30+
31+
/*!
32+
* \def MGIS_MAKE_UNIQUE(Type, e, ...)
33+
* \brief a simple wrapper around the `make_unique` function which handles the
34+
* declaration of the source location if needed.
35+
*
36+
* \param[in] Type: type of the object built
37+
* \param[in, out] ctx: execution context
38+
*/
39+
#ifdef MGIS_USE_SOURCE_LOCATION_INFORMATION
40+
#define MGIS_MAKE_UNIQUE(Type, e, ...) \
41+
::mgis::make_unique<Type>(e, std::source_location::current(), __VA_ARGS__)
42+
#else
43+
#define MGIS_MAKE_UNIQUE(Type, e, ...) ::mgis::make_unique<Type>(e, __VA_ARGS__)
44+
#endif
45+
46+
/*!
47+
* \def MGIS_MAKE_UNIQUE_AS(Type, e, ...)
48+
* \brief a simple wrapper around the `make_unique_as` function which handles
49+
* the declaration of the source location if needed
50+
*
51+
* \param[in] Type: type of the object built
52+
* \param[in, out] ctx: execution context
53+
*/
54+
#ifdef MGIS_USE_SOURCE_LOCATION_INFORMATION
55+
#define MGIS_MAKE_UNIQUE_AS(BaseType, Type, e, ...) \
56+
::mgis::make_unique_as<BaseType, Type>(e, std::source_location::current(), \
57+
__VA_ARGS__)
58+
#else
59+
#define MGIS_MAKE_UNIQUE_AS(BaseType, Type, e, ...) \
60+
::mgis::make_unique_as<BaseType, Type>(e, __VA_ARGS__)
61+
#endif
62+
63+
/*!
64+
* \def MGIS_MAKE_SHARED(Type, e, ...)
65+
* \brief a simple wrapper around the `make_shared` function which handles the
66+
* declaration of the source location if needed
67+
*
68+
* \param[in] Type: type of the object built
69+
* \param[in, out] ctx: execution context
70+
*/
71+
#ifdef MGIS_USE_SOURCE_LOCATION_INFORMATION
72+
#define MGIS_MAKE_SHARED(Type, e, ...) \
73+
::mgis::make_shared<Type>(e, std::source_location::current(), __VA_ARGS__)
74+
#else
75+
#define MGIS_MAKE_SHARED_AS(BaseType, Type, e, ...) \
76+
::mgis::make_shared_as<BaseType, Type>(e, __VA_ARGS__)
77+
#endif
78+
79+
/*!
80+
* \def MGIS_MAKE_SHARED_AS(Type, e, ...)
81+
* \brief a simple wrapper around the `make_shared_as` function which handles
82+
* the declaration of the source location if needed.
83+
*
84+
* \param[in] Type: type of the object built
85+
* \param[in, out] ctx: execution context
86+
*/
87+
#ifdef MGIS_USE_SOURCE_LOCATION_INFORMATION
88+
#define MGIS_MAKE_SHARED_AS(BaseType, Type, e, ...) \
89+
::mgis::make_shared_as<BaseType, Type>(e, std::source_location::current(), \
90+
__VA_ARGS__)
91+
#else
92+
#define MGIS_MAKE_SHARED(Type, e, ...) ::mgis::make_shared<Type>(e, __VA_ARGS__)
93+
#endif
94+
95+
/*!
96+
* \brief an helper macro to build a variable the constructor of which may throw
97+
*
98+
* \param[in] Type: type of the object built
99+
* \param[in] v: name of the variable built
100+
* \param[in, out] ctx: execution context
101+
*/
102+
#define MGIS_TRY_CONSTRUCT(Type, v, e, ...) \
103+
std::optional<Type> MGIS_TEMPORARY_VARIABLE(v) = \
104+
MGIS_CONSTRUCT(Type, e, __VA_ARGS__); \
105+
if (!MGIS_TEMPORARY_VARIABLE(v).has_value()) { \
106+
return InvalidResult{}; \
107+
} \
108+
Type &v = *(MGIS_TEMPORARY_VARIABLE(v));
109+
110+
/*!
111+
* \brief an helper macro to build an unique pointer for type the constructor of
112+
* which may throw
113+
*
114+
* \param[in] Type: type of the object built
115+
* \param[in] v: name of the variable built
116+
* \param[in, out] ctx: execution context
117+
*/
118+
#define MGIS_TRY_MAKE_UNIQUE(Type, v, e, ...) \
119+
std::unique_ptr<Type> v = MGIS_MAKE_UNIQUE(Type, e, __VA_ARGS__); \
120+
if (v.get() == nullptr) { \
121+
return InvalidResult{}; \
122+
}
123+
124+
/*!
125+
* \brief an helper macro to build an unique pointer for type the constructor of
126+
* which may throw
127+
*
128+
* \param[in] BaseType: pointer to a base type
129+
* \param[in] Type: type of the object built
130+
* \param[in] v: name of the variable built
131+
* \param[in, out] ctx: execution context
132+
*/
133+
#define MGIS_TRY_MAKE_UNIQUE_AS(BaseType, Type, v, e, ...) \
134+
std::unique_ptr<BaseType> v = \
135+
MGIS_MAKE_UNIQUE_AS(BaseType, Type, e, __VA_ARGS__); \
136+
if (v.get() == nullptr) { \
137+
return InvalidResult{}; \
138+
}
139+
140+
/*!
141+
* \brief an helper macro to build an shared pointer for type the constructor of
142+
* which may throw
143+
*
144+
* \param[in] Type: type of the object built
145+
* \param[in] v: name of the variable built
146+
* \param[in, out] ctx: execution context
147+
*/
148+
#define MGIS_TRY_MAKE_SHARED(Type, v, e, ...) \
149+
std::shared_ptr<Type> v = MGIS_MAKE_SHARED(Type, e, __VA_ARGS__); \
150+
if (v.get() == nullptr) { \
151+
return InvalidResult{}; \
152+
}
153+
154+
/*!
155+
* \brief an helper macro to build an shared pointer for type the constructor of
156+
* which may throw
157+
*
158+
* \param[in] BaseType: pointer to a base type
159+
* \param[in] Type: type of the object built
160+
* \param[in] v: name of the variable built
161+
* \param[in, out] ctx: execution context
162+
*/
163+
#define MGIS_TRY_MAKE_SHARED_AS(BaseType, Type, v, e, ...) \
164+
std::shared_ptr<BaseType> v = \
165+
MGIS_MAKE_SHARED_AS(BaseType, Type, e, __VA_ARGS__); \
166+
if (v.get() == nullptr) { \
167+
return InvalidResult{}; \
168+
}
169+
170+
namespace mgis {
171+
172+
#ifdef MGIS_USE_SOURCE_LOCATION_INFORMATION
173+
174+
/*!
175+
* \brief try to build an object of the given type.
176+
*
177+
* The constructor of the object may throw. In this case, the exception thrown
178+
* is catched and the information hold by the exception is added to the list
179+
* of registered error messages.
180+
*
181+
* \tparam Type: type to build.
182+
* \tparam ArgumentsTypes: types of the arguments passed to the constructor.
183+
* \param[in, out] ctx: execution context
184+
* \param[in] args: arguments passed to the constructor
185+
*/
186+
template <typename Type, typename... ArgumentsTypes>
187+
[[nodiscard]] std::optional<Type> construct(
188+
Context &,
189+
const std::source_location &,
190+
ArgumentsTypes &&...) noexcept requires
191+
std::is_constructible_v<std::remove_const_t<Type>, ArgumentsTypes...>;
192+
/*!
193+
* \brief try to build a unique pointer holding the given type.
194+
*
195+
* The constructor of the object may throw. In this case, the exception thrown
196+
* is catched and the information hold by the exception is added to the list
197+
* of registered error messages.
198+
*
199+
* \tparam BaseType: base type used to store the build object.
200+
* \tparam Type: type to build.
201+
* \tparam ArgumentsTypes: types of the arguments passed to the constructor.
202+
* \param[in, out] ctx: execution context
203+
* \param[in] args: arguments passed to the constructor
204+
*/
205+
template <typename Type, typename... ArgumentsTypes>
206+
[[nodiscard]] std::unique_ptr<Type> make_unique(
207+
Context &,
208+
const std::source_location &,
209+
ArgumentsTypes &&...) noexcept requires
210+
std::is_constructible_v<std::remove_const_t<Type>, ArgumentsTypes...>;
211+
/*!
212+
* \brief try to build a unique pointer of a base type holding the given type.
213+
*
214+
* The constructor of the object may throw. In this case, the exception thrown
215+
* is catched and the information hold by the exception is added to the list
216+
* of registered error messages.
217+
*
218+
* \tparam BaseType: base type used to store the build object.
219+
* \tparam Type: type to build.
220+
* \tparam ArgumentsTypes: types of the arguments passed to the constructor.
221+
* \param[in, out] ctx: execution context
222+
* \param[in] args: arguments passed to the constructor
223+
*/
224+
template <typename BaseType, typename Type, typename... ArgumentsTypes>
225+
[[nodiscard]] std::unique_ptr<BaseType> make_unique_as(
226+
Context &, const std::source_location &, ArgumentsTypes &&...) noexcept
227+
requires std::is_base_of_v<BaseType, Type> &&
228+
std::is_constructible_v<std::remove_const_t<Type>, ArgumentsTypes...>;
229+
/*!
230+
* \brief try to build a shared pointer holding the given type.
231+
*
232+
* The constructor of the object may throw. In this case, the exception thrown
233+
* is catched and the information hold by the exception is added to the list
234+
* of registered error messages.
235+
*
236+
* \tparam Type: type to build.
237+
* \tparam ArgumentsTypes: types of the arguments passed to the constructor.
238+
* \param[in, out] ctx: execution context
239+
* \param[in] args: arguments passed to the constructor
240+
*/
241+
template <typename Type, typename... ArgumentsTypes>
242+
[[nodiscard]] std::shared_ptr<Type> make_shared(
243+
Context &,
244+
const std::source_location &,
245+
ArgumentsTypes &&...) noexcept requires
246+
std::is_constructible_v<std::remove_const_t<Type>, ArgumentsTypes...>;
247+
/*!
248+
* \brief try to build a shared pointer of a base type holding the given type.
249+
*
250+
* The constructor of the object may throw. In this case, the exception thrown
251+
* is catched and the information hold by the exception is added to the list
252+
* of registered error messages.
253+
*
254+
* \tparam BaseType: base type used to store the build object.
255+
* \tparam Type: type to build.
256+
* \tparam ArgumentsTypes: types of the arguments passed to the constructor.
257+
* \param[in, out] ctx: execution context
258+
* \param[in] args: arguments passed to the constructor
259+
*/
260+
template <typename BaseType, typename Type, typename... ArgumentsTypes>
261+
[[nodiscard]] std::shared_ptr<BaseType> make_shared_as(
262+
Context &, const std::source_location &, ArgumentsTypes &&...) noexcept
263+
requires std::is_base_of_v<BaseType, Type> &&
264+
std::is_constructible_v<std::remove_const_t<Type>, ArgumentsTypes...>;
265+
266+
#endif
267+
268+
/*!
269+
* \brief try to build an object of the given type.
270+
*
271+
* The constructor of the object may throw. In this case, the exception thrown
272+
* is catched and the information hold by the exception is added to the list
273+
* of registered error messages.
274+
*
275+
* \tparam Type: type to build.
276+
* \tparam ArgumentsTypes: types of the arguments passed to the constructor.
277+
* \param[in, out] ctx: execution context
278+
* \param[in] args: arguments passed to the constructor
279+
*/
280+
template <typename Type, typename... ArgumentsTypes>
281+
[[nodiscard]] std::optional<Type> construct(
282+
Context &, ArgumentsTypes &&...) noexcept requires
283+
std::is_constructible_v<std::remove_const_t<Type>, ArgumentsTypes...>;
284+
/*!
285+
* \brief try to build a unique pointer holding the given type.
286+
*
287+
* The constructor of the object may throw. In this case, the exception thrown
288+
* is catched and the information hold by the exception is added to the list
289+
* of registered error messages.
290+
*
291+
* \tparam BaseType: base type used to store the build object.
292+
* \tparam Type: type to build.
293+
* \tparam ArgumentsTypes: types of the arguments passed to the constructor.
294+
* \param[in, out] ctx: execution context
295+
* \param[in] args: arguments passed to the constructor
296+
*/
297+
template <typename Type, typename... ArgumentsTypes>
298+
[[nodiscard]] std::unique_ptr<Type> make_unique(
299+
Context &, ArgumentsTypes &&...) noexcept requires
300+
std::is_constructible_v<std::remove_const_t<Type>, ArgumentsTypes...>;
301+
/*!
302+
* \brief try to build a unique pointer of a base type holding the given type.
303+
*
304+
* The constructor of the object may throw. In this case, the exception thrown
305+
* is catched and the information hold by the exception is added to the list
306+
* of registered error messages.
307+
*
308+
* \tparam BaseType: base type used to store the build object.
309+
* \tparam Type: type to build.
310+
* \tparam ArgumentsTypes: types of the arguments passed to the constructor.
311+
* \param[in, out] ctx: execution context
312+
* \param[in] args: arguments passed to the constructor
313+
*/
314+
template <typename BaseType, typename Type, typename... ArgumentsTypes>
315+
[[nodiscard]] std::unique_ptr<BaseType> make_unique_as(
316+
Context &, ArgumentsTypes &&...) noexcept requires
317+
std::is_base_of_v<BaseType, Type> &&
318+
std::is_constructible_v<std::remove_const_t<Type>, ArgumentsTypes...>;
319+
/*!
320+
* \brief try to build a shared pointer holding the given type.
321+
*
322+
* The constructor of the object may throw. In this case, the exception thrown
323+
* is catched and the information hold by the exception is added to the list
324+
* of registered error messages.
325+
*
326+
* \tparam Type: type to build.
327+
* \tparam ArgumentsTypes: types of the arguments passed to the constructor.
328+
* \param[in, out] ctx: execution context
329+
* \param[in] args: arguments passed to the constructor
330+
*/
331+
template <typename Type, typename... ArgumentsTypes>
332+
[[nodiscard]] std::shared_ptr<Type> make_shared(
333+
Context &, ArgumentsTypes &&...) noexcept requires
334+
std::is_constructible_v<std::remove_const_t<Type>, ArgumentsTypes...>;
335+
/*!
336+
* \brief try to build a shared pointer of a base type holding the given type.
337+
*
338+
* The constructor of the object may throw. In this case, the exception thrown
339+
* is catched and the information hold by the exception is added to the list
340+
* of registered error messages.
341+
*
342+
* \tparam BaseType: base type used to store the build object.
343+
* \tparam Type: type to build.
344+
* \tparam ArgumentsTypes: types of the arguments passed to the constructor.
345+
* \param[in, out] ctx: execution context
346+
* \param[in] args: arguments passed to the constructor
347+
*/
348+
template <typename BaseType, typename Type, typename... ArgumentsTypes>
349+
[[nodiscard]] std::shared_ptr<BaseType> make_shared_as(
350+
Context &, ArgumentsTypes &&...) noexcept requires
351+
std::is_base_of_v<BaseType, Type> &&
352+
std::is_constructible_v<std::remove_const_t<Type>, ArgumentsTypes...>;
353+
354+
} // end of namespace mgis
355+
356+
#include "MGIS/Utilities/Construct.ixx"
357+
358+
#endif /* LIB_MGIS_UTILITIES_CONSTRUCT_HXX */

0 commit comments

Comments
 (0)