KaMPIng 0.1.1
Flexible and (near) zero-overhead C++ bindings for MPI
Loading...
Searching...
No Matches
named_parameter_check.hpp
Go to the documentation of this file.
1// This file is part of KaMPIng.
2//
3// Copyright 2022 The KaMPIng Authors
4//
5// KaMPIng is free software : you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
6// License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later
7// version. KaMPIng is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
9// for more details.
10//
11// You should have received a copy of the GNU Lesser General Public License along with KaMPIng. If not, see
12// <https://www.gnu.org/licenses/>.
13
14/// @file
15/// @brief Template magic to check named parameters passed to wrappers at compile time.
16
17#pragma once
18
19#include <tuple>
20#include <type_traits>
21
24#include "kamping/serialization.hpp"
25
26// The following macros look strange since they use a GNU extension that becomes obsolete with C++-20.
27// The extension is supported by all major compilers.
28// Semantic is as follows: if the variadic parameters of a macro is empty,
29//
30// , ##__VA_ARGS__
31//
32// expands to nothing, i.e., the comma vanishes. Otherwise, the comma stays.
33// This is required because we overload macros based on their number of arguments; however, the preprocessor
34// considers an empty argument to be one argument, i.e., if we have a variadic macro
35//
36// #define M(...)
37//
38// and call it as M(), we actually call it with one argument: the empty argument. But since we decide what to do with M
39// based on the number of arguments passed to it, we need a way to distinguish between "1 empty argument" and "1
40// actual argument".
41//
42// Using this trick, "zero arguments" as in "1 argument, but empty" resolves to <empty>, while 1 actual argument
43// resolves to ", <argument>", i.e., 2 arguments.
44//
45// However, this leads to the situation where the first argument of this macro is always empty; that's why we have
46// a lot of "ignore" parameters in the remaining macros of this file.
47
48/// @brief Wrapper to pass (possibly empty) list of parameter type names as required parameters to \c
49/// KAMPING_CHECK_PARAMETERS.
50/// Note that this macro only takes the *name* of parameter types, i.e., instead of using
51/// `kamping::internal::ParameterType::send_buf`, only pass `send_buf` to this macro.
52#define KAMPING_REQUIRED_PARAMETERS(...) , ##__VA_ARGS__
53
54/// @brief Wrapper to pass (possibly empty) list of parameter type names as optional parameters to \c
55/// KAMPING_CHECK_PARAMETERS.
56/// Note that this macro only takes the *name* of parameter types, i.e., instead of using
57/// `kamping::internal::ParameterType::send_buf`, only pass `send_buf` to this macro.
58#define KAMPING_OPTIONAL_PARAMETERS(...) , ##__VA_ARGS__
59
60/// @brief Assertion macro that checks if passed parameters are correct, i.e., all parameter types are unique, all
61/// required parameters are provided, and no unused parameter is passed. Also checks that all parameter types are
62/// r-value references.
63///
64/// The macro *only* expects the parameter type, i.e., a member name of the `kamping::internal::ParameterType` enum
65/// *without the name of the enum*. For instance,
66/// ```c++
67/// KAMPING_CHECK_PARAMETERS(Args, KAMPING_REQUIRED_PARAMETERS(send_buf, recv_buf), KAMPING_OPTIONAL_PARAMETERS())
68/// ```
69/// checks that the parameter pack `Args` contains members of type `kamping::internal::ParameterType::send_buf` and type
70/// `kamping::internal::ParameterType::recv_buf`.
71///
72/// Note that expanding the macro into a `do { ... } while(false)` pseudo-loop is a common trick to make a macro
73/// "act like a statement". Otherwise, it would have surprising effects if the macro is used inside a `if` branch
74/// without braces.
75///
76/// @param args A parameter pack with all parameter types passed to the function. Note that this is only the name of the
77/// parameter pack *without trailing `...`*.
78/// @param required A list of required parameter type names wrapped in a KAMPING_REQUIRED_PARAMETERS macro.
79/// @param optional A list of optional parameter type names wrapped in a KAMPING_OPTIONAL_PARAMETERS macro.
80#define KAMPING_CHECK_PARAMETERS(args, required, optional) \
81 do { \
82 KAMPING_PARAMETER_CHECK_HPP_ASSERT_REQUIRED_PARAMETERS(args, required); \
83 \
84 using required_parameters_types = typename kamping::internal::parameter_types_to_integral_constants< \
85 KAMPING_PARAMETER_CHECK_HPP_PREFIX_PARAMETERS(required)>::type; \
86 using optional_parameters_types = typename kamping::internal::parameter_types_to_integral_constants< \
87 KAMPING_PARAMETER_CHECK_HPP_PREFIX_PARAMETERS(optional)>::type; \
88 using parameter_types = typename kamping::internal::parameters_to_integral_constant<args...>::type; \
89 static_assert( \
90 kamping::internal:: \
91 has_no_unused_parameters<required_parameters_types, optional_parameters_types, args...>::assertion, \
92 "There are unsupported parameters, only support required " \
93 "parameters " KAMPING_PARAMETER_CHECK_HPP_EVAL_STRINGIFY(required \
94 ) " and optional parameters " KAMPING_PARAMETER_CHECK_HPP_EVAL_STRINGIFY(optional) \
95 ); \
96 static_assert(kamping::internal::all_unique_v<parameter_types>, "There are duplicate parameter types."); \
97 } while (false)
98
99/// @cond IMPLEMENTATION
100
101// Used to stringify variadic parameters:
102// KAMPING_PARAMETER_CHECK_HPP_EVAL_STRINGIFY(a, b, c) returns the string "a, b, c"
103#define KAMPING_PARAMETER_CHECK_HPP_EVAL_STRINGIFY(ignore, ...) "[" #__VA_ARGS__ "]"
104
105// In the following, we implement variadic macros that do something for each of their arguments:
106// - KAMPING_PARAMETER_CHECK_HPP_PREFIX_PARAMETERS(...) prepends each argument by "kamping::internal::ParameterType::"
107// - KAMPING_PARAMETER_CHECK_HPP_ASSERT_REQUIRED_PARAMETERS(args, ...) generates a static assert for each of its
108// arguments to ensure that args... contains a parameter of that type.
109//
110// Since doing something "for each" argument of a variadic macro is unsupported by the preprocessor, we use two
111// hacks to implement these macros:
112// - Instead of a "for each" loop, we implement macros Xi, for 1 <= i <= 9, such that Xi takes i arguments
113// and generates the same code as a "for each" loop would generate for these i arguments.
114// - A dispatch macro chooses the right Xi macro depending on the number of arguments passed to the dispatch macro.
115//
116// First, we define the macros for various number of arguments:
117//
118// ```
119// #define X0 [...]
120// #define X1(a) [...]
121// #define X2(a, b) [...]
122// ```
123//
124// Now, we need a "dispatch" macro `X` that can take 0, 1 or 2 arguments and resolve to `X0`, `X1` or `X2`. While we
125// can't make the macro to take between 0 and 2 arguments, we can define it as a variadic macro:
126//
127// ```
128// #define X(...) [... magic that expands to X2, X1 or X0 depending on the number of arguments passed to X ...]
129// ```
130//
131// To implement this macro, we first need a helper:
132//
133// ```
134// #define DISPATCH(x2, x1, x, ...) x
135// ```
136//
137// `DISPATCH` takes at least 3 arguments and substitutes to whatever we pass as 3rd argument, e.g.:
138//
139// ```
140// DISPATCH(a, b, c, d, e, f) // becomes c
141// DISPATCH(0, 1, X2(0, 1), X1(0, 1), X0) // becomes X2(0, 1)
142// DISPATCH(0, X2(0), X1(0), X0) // becomes X1(0)
143// DISPATCH(X2(), X1(), X0) // becomes X0
144// ```
145//
146// At least in theory -- if one strictly adheres to the C++ standard, `DISPATCH` actually takes at least 4 arguments,
147// since the `...` parameter may not be empty. Thus, in our implementation, we pass another dummy argument to the
148// `DISPATCH` invocation, e.g:
149// ```
150// DISPATCH(X2(), X1(), X0, ignore)
151// ```
152//
153// We can use that to implement `X`:
154//
155// ```
156// #define X(...) DISPATCH(__VA_ARGS__, X2(__VA_ARGS__), X1(__VA_ARGS__), X0, ignore)
157// ```
158//
159// `__VA_ARGS__` expands to whatever arguments we pass to `X`. Thus, if we pass 2 arguments to `X`, it also expands to
160// two arguments. If we pass 1 argument to `X`, it expands to 1 argument. Thus, we can "move" the correct implementation
161// for `X` to be the 3rd argument passed to `DISPATCH`:
162//
163// * `X(0, 1)` becomes `DISPATCH(0, 1, X2(0, 1), X1(0, 1), X0, ignore)` becomes `X2(0, 1)`
164//
165// * `X(0)` becomes `DISPATCH(0, X2(0), X1(0), X0, ignore)` becomes `X1(0)`
166//
167// Since KAMPING_REQUIRED_PARAMETERS and KAMPING_OPTIONAL_PARAMETERS always resolve to at least one argument (see
168// description above), this is sufficient.
169
170// DISPATCH helper macro as described above
171#define KAMPING_PARAMETER_CHECK_HPP_SELECT10(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, y, ...) y
172
173// Adds the prefix "kamping::internal::ParameterType::" to each of its arguments (up to 10 arguments)
174// I.e., turns "send_buf, recv_buf" into "kamping::internal::ParameterType::send_buf,
175// kamping::internal::ParameterType::recv_buf"
176//
177// We do this because we need both versions of the parameter types: to print nice error messages, we only need the names
178// of the types without preceding `kamping::internal::ParameterType::`; to implement the checks, we need the actual
179// name of the symbol to generate valid C++ code.
180//
181// Note that argument "ignore" argument in this macro is required because the "..." parameter of
182// KAMPING_PARAMETER_CHECK_HPP_SELECT10 may not be empty.
183#define KAMPING_PARAMETER_CHECK_HPP_PREFIX_PARAMETERS(...) \
184 KAMPING_PARAMETER_CHECK_HPP_SELECT10( \
185 __VA_ARGS__, \
186 KAMPING_PARAMETER_CHECK_HPP_PREFIX9(__VA_ARGS__), \
187 KAMPING_PARAMETER_CHECK_HPP_PREFIX8(__VA_ARGS__), \
188 KAMPING_PARAMETER_CHECK_HPP_PREFIX7(__VA_ARGS__), \
189 KAMPING_PARAMETER_CHECK_HPP_PREFIX6(__VA_ARGS__), \
190 KAMPING_PARAMETER_CHECK_HPP_PREFIX5(__VA_ARGS__), \
191 KAMPING_PARAMETER_CHECK_HPP_PREFIX4(__VA_ARGS__), \
192 KAMPING_PARAMETER_CHECK_HPP_PREFIX3(__VA_ARGS__), \
193 KAMPING_PARAMETER_CHECK_HPP_PREFIX2(__VA_ARGS__), \
194 KAMPING_PARAMETER_CHECK_HPP_PREFIX1(__VA_ARGS__), \
195 KAMPING_PARAMETER_CHECK_HPP_PREFIX0(__VA_ARGS__), \
196 ignore \
197 )
198
199#define KAMPING_PARAMETER_CHECK_HPP_PREFIX0(ignore)
200#define KAMPING_PARAMETER_CHECK_HPP_PREFIX1(ignore, x1) kamping::internal::ParameterType::x1
201#define KAMPING_PARAMETER_CHECK_HPP_PREFIX2(ignore, x1, x2) \
202 KAMPING_PARAMETER_CHECK_HPP_PREFIX1(ignore, x1), KAMPING_PARAMETER_CHECK_HPP_PREFIX1(ignore, x2)
203#define KAMPING_PARAMETER_CHECK_HPP_PREFIX3(ignore, x1, x2, x3) \
204 KAMPING_PARAMETER_CHECK_HPP_PREFIX2(ignore, x1, x2), KAMPING_PARAMETER_CHECK_HPP_PREFIX1(ignore, x3)
205#define KAMPING_PARAMETER_CHECK_HPP_PREFIX4(ignore, x1, x2, x3, x4) \
206 KAMPING_PARAMETER_CHECK_HPP_PREFIX3(ignore, x1, x2, x3), KAMPING_PARAMETER_CHECK_HPP_PREFIX1(ignore, x4)
207#define KAMPING_PARAMETER_CHECK_HPP_PREFIX5(ignore, x1, x2, x3, x4, x5) \
208 KAMPING_PARAMETER_CHECK_HPP_PREFIX4(ignore, x1, x2, x3, x4), KAMPING_PARAMETER_CHECK_HPP_PREFIX1(ignore, x5)
209#define KAMPING_PARAMETER_CHECK_HPP_PREFIX6(ignore, x1, x2, x3, x4, x5, x6) \
210 KAMPING_PARAMETER_CHECK_HPP_PREFIX5(ignore, x1, x2, x3, x4, x5), KAMPING_PARAMETER_CHECK_HPP_PREFIX1(ignore, x6)
211#define KAMPING_PARAMETER_CHECK_HPP_PREFIX7(ignore, x1, x2, x3, x4, x5, x6, x7) \
212 KAMPING_PARAMETER_CHECK_HPP_PREFIX6(ignore, x1, x2, x3, x4, x5, x6), KAMPING_PARAMETER_CHECK_HPP_PREFIX1(ignore, x7)
213#define KAMPING_PARAMETER_CHECK_HPP_PREFIX8(ignore, x1, x2, x3, x4, x5, x6, x7, x8) \
214 KAMPING_PARAMETER_CHECK_HPP_PREFIX7(ignore, x1, x2, x3, x4, x5, x6, x7), \
215 KAMPING_PARAMETER_CHECK_HPP_PREFIX1(ignore, x8)
216#define KAMPING_PARAMETER_CHECK_HPP_PREFIX9(ignore, x1, x2, x3, x4, x5, x6, x7, x8, x9) \
217 KAMPING_PARAMETER_CHECK_HPP_PREFIX8(ignore, x1, x2, x3, x4, x5, x6, x7, x8), \
218 KAMPING_PARAMETER_CHECK_HPP_PREFIX1(ignore, x9)
219
220// Generate code that checks that each of the given parameter types are present in args...
221// Usage: KAMPING_PARAMETER_CHECK_HPP_ASSERT_REQUIRED_PARAMETERS(Args, send_buf, recv_buf)
222// Checks that Args... has parameters for kamping::internal::ParameterType::send_buf and
223// kamping::internal::ParameterType::recv_buf
224//
225// Note that the "ignore" argument in this macro is required because the "..." parameter of
226// KAMPING_PARAMETER_CHECK_HPP_SELECT10 may not be empty.
227#define KAMPING_PARAMETER_CHECK_HPP_ASSERT_REQUIRED_PARAMETERS(args, ...) \
228 KAMPING_PARAMETER_CHECK_HPP_SELECT10( \
229 __VA_ARGS__, \
230 KAMPING_PARAMETER_CHECK_HPP_ASSERT_REQUIRED_PARAMETER9(args, __VA_ARGS__), \
231 KAMPING_PARAMETER_CHECK_HPP_ASSERT_REQUIRED_PARAMETER8(args, __VA_ARGS__), \
232 KAMPING_PARAMETER_CHECK_HPP_ASSERT_REQUIRED_PARAMETER7(args, __VA_ARGS__), \
233 KAMPING_PARAMETER_CHECK_HPP_ASSERT_REQUIRED_PARAMETER6(args, __VA_ARGS__), \
234 KAMPING_PARAMETER_CHECK_HPP_ASSERT_REQUIRED_PARAMETER5(args, __VA_ARGS__), \
235 KAMPING_PARAMETER_CHECK_HPP_ASSERT_REQUIRED_PARAMETER4(args, __VA_ARGS__), \
236 KAMPING_PARAMETER_CHECK_HPP_ASSERT_REQUIRED_PARAMETER3(args, __VA_ARGS__), \
237 KAMPING_PARAMETER_CHECK_HPP_ASSERT_REQUIRED_PARAMETER2(args, __VA_ARGS__), \
238 KAMPING_PARAMETER_CHECK_HPP_ASSERT_REQUIRED_PARAMETER1(args, __VA_ARGS__), \
239 KAMPING_PARAMETER_CHECK_HPP_ASSERT_REQUIRED_PARAMETER0(args, __VA_ARGS__), \
240 ignore \
241 )
242
243#define KAMPING_PARAMETER_CHECK_HPP_ASSERT_REQUIRED_PARAMETER0(args, ignore)
244#define KAMPING_PARAMETER_CHECK_HPP_ASSERT_REQUIRED_PARAMETER1(args, ignore, x1) \
245 static_assert( \
246 kamping::internal::has_parameter_type<kamping::internal::ParameterType::x1, args...>(), \
247 "Missing required parameter " #x1 \
248 );
249#define KAMPING_PARAMETER_CHECK_HPP_ASSERT_REQUIRED_PARAMETER2(args, ignore, x1, x2) \
250 KAMPING_PARAMETER_CHECK_HPP_ASSERT_REQUIRED_PARAMETER1(args, ignore, x1); \
251 KAMPING_PARAMETER_CHECK_HPP_ASSERT_REQUIRED_PARAMETER1(args, ignore, x2)
252#define KAMPING_PARAMETER_CHECK_HPP_ASSERT_REQUIRED_PARAMETER3(args, ignore, x1, x2, x3) \
253 KAMPING_PARAMETER_CHECK_HPP_ASSERT_REQUIRED_PARAMETER2(args, ignore, x1, x2); \
254 KAMPING_PARAMETER_CHECK_HPP_ASSERT_REQUIRED_PARAMETER1(args, ignore, x3)
255#define KAMPING_PARAMETER_CHECK_HPP_ASSERT_REQUIRED_PARAMETER4(args, ignore, x1, x2, x3, x4) \
256 KAMPING_PARAMETER_CHECK_HPP_ASSERT_REQUIRED_PARAMETER3(args, ignore, x1, x2, x3); \
257 KAMPING_PARAMETER_CHECK_HPP_ASSERT_REQUIRED_PARAMETER1(args, ignore, x4)
258#define KAMPING_PARAMETER_CHECK_HPP_ASSERT_REQUIRED_PARAMETER5(args, ignore, x1, x2, x3, x4, x5) \
259 KAMPING_PARAMETER_CHECK_HPP_ASSERT_REQUIRED_PARAMETER4(args, ignore, x1, x2, x3, x4); \
260 KAMPING_PARAMETER_CHECK_HPP_ASSERT_REQUIRED_PARAMETER1(args, ignore, x5)
261#define KAMPING_PARAMETER_CHECK_HPP_ASSERT_REQUIRED_PARAMETER6(args, ignore, x1, x2, x3, x4, x5, x6) \
262 KAMPING_PARAMETER_CHECK_HPP_ASSERT_REQUIRED_PARAMETER5(args, ignore, x1, x2, x3, x4, x5); \
263 KAMPING_PARAMETER_CHECK_HPP_ASSERT_REQUIRED_PARAMETER1(args, ignore, x6)
264#define KAMPING_PARAMETER_CHECK_HPP_ASSERT_REQUIRED_PARAMETER7(args, ignore, x1, x2, x3, x4, x5, x6, x7) \
265 KAMPING_PARAMETER_CHECK_HPP_ASSERT_REQUIRED_PARAMETER6(args, ignore, x1, x2, x3, x4, x5, x6); \
266 KAMPING_PARAMETER_CHECK_HPP_ASSERT_REQUIRED_PARAMETER1(args, ignore, x7)
267#define KAMPING_PARAMETER_CHECK_HPP_ASSERT_REQUIRED_PARAMETER8(args, ignore, x1, x2, x3, x4, x5, x6, x7, x8) \
268 KAMPING_PARAMETER_CHECK_HPP_ASSERT_REQUIRED_PARAMETER7(args, ignore, x1, x2, x3, x4, x5, x6, x7); \
269 KAMPING_PARAMETER_CHECK_HPP_ASSERT_REQUIRED_PARAMETER1(args, ignore, x8)
270#define KAMPING_PARAMETER_CHECK_HPP_ASSERT_REQUIRED_PARAMETER9(args, ignore, x1, x2, x3, x4, x5, x6, x7, x8, x9) \
271 KAMPING_PARAMETER_CHECK_HPP_ASSERT_REQUIRED_PARAMETER8(args, ignore, x1, x2, x3, x4, x5, x6, x7, x8); \
272 KAMPING_PARAMETER_CHECK_HPP_ASSERT_REQUIRED_PARAMETER1(args, ignore, x9)
273
274/// @brief Assertion macro that checks if a parameter type is not present in the arguments.
275/// Outputs a static assert if the parameter type is present in the arguments with text "Parameter type <parameter_type>
276/// is not supported <whatfor>."
277#define KAMPING_UNSUPPORTED_PARAMETER(args, parameter_type, whatfor) \
278 static_assert( \
279 !kamping::internal::has_parameter_type<kamping::internal::ParameterType::parameter_type, args...>(), \
280 "Parameter type " #parameter_type " is not supported " #whatfor "." \
281 )
282
283/// @endcond
284
285namespace kamping::internal {
286/// @brief Struct wrapping a check that verifies that no unused parameters are part of the arguments.
287///
288/// @tparam RequiredParametersTuple All required kamping::internal::ParameterType passed as \c
289/// std::integral_constant in an \c std::tuple.
290/// @tparam OptionalParametersTuple All optional kamping::internal::ParameterType passed as \c
291/// std::integral_constant in an \c std::tuple.
292/// @tparam Args Arguments passed to the function that calls this check, i.e., the different parameters.
293template <typename RequiredParametersTuple, typename OptionalParametersTuple, typename... Args>
295 /// @brief Concatenation of required and optional parameters.
297
298 /// @brief Get total number of different parameters (passed, required, and optional).
299 ///
300 /// This check works similar to has_all_required_parameters. Here, we "iterate" over all parameters,
301 /// i.e., \c RequiredParametersTuple and \c OptionalParametersTuple and check which parameters are
302 /// not(!) passed as \c Args. Then, we add this number to the size of Args. If this number is
303 /// greater than the total number of (required and optional) parameters, there are unused
304 /// parameters.
305 ///
306 /// @tparam Indices Index sequence used to unpack all required parameters in \c ParametersTuple.
307 /// @param indices The parameter is only required to deduce the template parameter.
308 /// @return The number of different parameters (passed, optional, and required).
309 template <size_t... Indices>
310 static constexpr auto number_distinct_parameters(std::index_sequence<Indices...> indices [[maybe_unused]]) {
311 return std::tuple_size_v<decltype(std::tuple_cat(
312 std::conditional_t<
313 !has_parameter_type<std::tuple_element_t<Indices, all_available_parameters>::value, Args...>(),
314 std::tuple<std::tuple_element_t<Indices, all_available_parameters>>,
315 std::tuple<>>{}...
316 ))> + sizeof...(Args);
317 }
318
319 /// @brief \c true if and only if no unused parameter can be found in \c Args.
320 static constexpr bool assertion =
321 (std::tuple_size_v<all_available_parameters> >= number_distinct_parameters(
322 std::make_index_sequence<std::tuple_size_v<all_available_parameters>>{}
323 ));
324
325}; // struct has_no_unused_parameters
326
327/// @brief Base wrapper (\c std::integral_constant) to test if all types of a tuple are unique.
328/// @tparam Tuple Tuple for which is it checked whether all types are unique.
329template <typename Tuple>
330struct all_unique : std::true_type {};
331
332/// @brief Recursive wrapper (\c std::integral_constant) to test if all types of a tuple are unique.
333/// This is done by checking for each type whether the type occurs in the types of the tuple to the
334/// right. If this is true for any type/position, the types in the tuple are not unique.
335///
336/// @tparam T Parameter for which we check whether it is contained in the remaining tuple.
337/// @tparam Ts Remaining types of the tuple.
338template <typename T, typename... Ts>
339struct all_unique<std::tuple<T, Ts...>>
340 : std::conjunction<std::negation<std::disjunction<std::is_same<T, Ts>...>>, all_unique<std::tuple<Ts...>>> {};
341
342/// @brief \c true if and only if all types of the tuple are unique.
343template <typename Tuple>
345
346/// @brief Wrapper to get an \c std::integral_constant for a kamping::internal::ParameterType.
347/// @tparam T kamping::internal::ParameterType that is converted to an \c std::integral_constant.
348template <ParameterType T>
350 /// @brief kamping::internal::ParameterType as \c std::integral_constant.
351 using type = std::integral_constant<ParameterType, T>;
352};
353
354/// @brief Wrapper to get a tuple of \c std::integral_constant for each kamping::internal::ParameterType
355/// passed as template parameter that are extracted as tuple of \c std::integral_constant.
356/// @tparam Parameters Passed kamping::internal::ParameterType.
357template <ParameterType... ParameterTypes>
359 /// @brief Type of the tuple.
360 using type =
361 decltype(std::tuple_cat(std::tuple<typename parameter_type_to_integral_constant<ParameterTypes>::type>{}...));
362};
363
364/// @brief Wrapper to get a tuple of \c std::integral_constant for each kamping::internal::ParameterType
365/// of the parameters.
366/// @tparam Parameters Passed parameters for which the kamping::internal::ParameterType are extracted as
367/// \c std::integral_constant in a tuple.
368template <typename... Parameters>
370 /// @brief Type of the tuple.
371 using type = decltype(std::tuple_cat(
373 ));
374};
375
376/// @brief Checks if a data buffer with requested parameter type exists and it is an input parameter (i.e. its content
377/// does not have to be computed/deduced by KaMPIng).
378///
379/// @tparam parameter_type The parameter type for which a parameter should be found.
380/// @tparam Args All parameter types to be searched.
381/// @return \c true iff. `Args` contains a parameter of type `parameter_type` and this parameter is not an output
382/// buffer.
383template <ParameterType parameter_type, typename... Args>
384static constexpr bool is_parameter_given_as_in_buffer = []() {
386 if constexpr (found_pos >= sizeof...(Args)) {
387 return false;
388 } else {
389 using FoundType = std::tuple_element_t<found_pos, std::tuple<Args...>>;
390 return !FoundType::is_out_buffer;
391 }
392}();
393
394/// @brief Checks if the buffer has to be computed by kamping, i.e. if it is an output parameter or the buffer has been
395/// allocated by KaMPIng.
396/// @tparam BufferType The buffer type to be checked
397template <typename BufferType>
398static constexpr bool has_to_be_computed =
399 std::remove_reference_t<BufferType>::is_out_buffer || std::remove_reference_t<BufferType>::is_lib_allocated;
400
401/// @brief Checks if all buffers have to be computed by kamping, i.e., if all buffers are output parameters of the
402/// buffers have been allocated by kamping.
403/// @tparam BufferTypes Any number of buffers types to be checked.
404template <typename... BufferTypes>
406
407/// @brief Checks if any of the buffers have to be computed by kamping, i.e., if at least one buffer is an output
408/// parameter or has been allocated by kamping.
409/// @tparam BufferTypes Any number of buffers to be checked.
410template <typename... BufferTypes>
412
413/// @brief Checks if \p DataBufferType is a serialization buffer.
414template <typename DataBufferType>
416 typename std::remove_const_t<std::remove_reference_t<DataBufferType>>::MemberTypeWithConstAndRef>;
417
418} // namespace kamping::internal
STL-compatible allocator for requesting memory using the builtin MPI allocator.
Definition allocator.hpp:32
ParameterType
Each input parameter to one of the MPI calls wrapped by KaMPIng needs to has one of the following tag...
Definition named_parameter_types.hpp:33
constexpr bool has_parameter_type()
Checks if parameter with requested parameter type exists.
Definition named_parameter_selection.hpp:186
Template magic to implement named parameters in cpp.
File containing the parameter types used by the KaMPIng library.
Internal namespace marking the code that is not user-facing.
Definition collectives_helpers.hpp:20
static constexpr bool any_has_to_be_computed
Checks if any of the buffers have to be computed by kamping, i.e., if at least one buffer is an outpu...
Definition named_parameter_check.hpp:411
static constexpr bool buffer_uses_serialization
Checks if DataBufferType is a serialization buffer.
Definition named_parameter_check.hpp:415
constexpr bool is_serialization_buffer_v
Type trait to check if a type is a serialization buffer.
Definition serialization.hpp:114
static constexpr bool is_parameter_given_as_in_buffer
Checks if a data buffer with requested parameter type exists and it is an input parameter (i....
Definition named_parameter_check.hpp:384
static constexpr bool all_have_to_be_computed
Checks if all buffers have to be computed by kamping, i.e., if all buffers are output parameters of t...
Definition named_parameter_check.hpp:405
static constexpr bool all_unique_v
true if and only if all types of the tuple are unique.
Definition named_parameter_check.hpp:344
static constexpr bool has_to_be_computed
Checks if the buffer has to be computed by kamping, i.e. if it is an output parameter or the buffer h...
Definition named_parameter_check.hpp:398
STL namespace.
Base wrapper (std::integral_constant) to test if all types of a tuple are unique.
Definition named_parameter_check.hpp:330
Struct wrapping a check that verifies that no unused parameters are part of the arguments.
Definition named_parameter_check.hpp:294
static constexpr bool assertion
true if and only if no unused parameter can be found in Args.
Definition named_parameter_check.hpp:320
static constexpr auto number_distinct_parameters(std::index_sequence< Indices... > indices)
Get total number of different parameters (passed, required, and optional).
Definition named_parameter_check.hpp:310
decltype(std::tuple_cat(RequiredParametersTuple{}, OptionalParametersTuple{})) all_available_parameters
Concatenation of required and optional parameters.
Definition named_parameter_check.hpp:296
Wrapper to get an std::integral_constant for a kamping::internal::ParameterType.
Definition named_parameter_check.hpp:349
std::integral_constant< ParameterType, T > type
kamping::internal::ParameterType as std::integral_constant.
Definition named_parameter_check.hpp:351
Wrapper to get a tuple of std::integral_constant for each kamping::internal::ParameterType passed as ...
Definition named_parameter_check.hpp:358
decltype(std::tuple_cat(std::tuple< typename parameter_type_to_integral_constant< ParameterTypes >::type >{}...)) type
Type of the tuple.
Definition named_parameter_check.hpp:360
Wrapper to get a tuple of std::integral_constant for each kamping::internal::ParameterType of the par...
Definition named_parameter_check.hpp:369
decltype(std::tuple_cat( std::tuple< typename parameter_type_to_integral_constant< Parameters::parameter_type >::type >{}...)) type
Type of the tuple.
Definition named_parameter_check.hpp:371