userver
C++ Async Framework
Toggle main menu visibility
Loading...
Searching...
No Matches
struct_subsets.hpp
Go to the documentation of this file.
1
#
pragma
once
2
3
/// @file userver/utils/struct_subsets.hpp
4
/// @brief Utilities for creating a struct with a subset of fields of the
5
/// original struct, with conversions between them.
6
7
#
include
<
type_traits
>
8
#
include
<
utility
>
9
10
#
include
<
boost
/
preprocessor
/
empty
.
hpp
>
11
#
include
<
boost
/
preprocessor
/
seq
/
for_each
.
hpp
>
12
13
#
include
<
userver
/
utils
/
forward_like
.
hpp
>
14
#
include
<
userver
/
utils
/
impl
/
boost_variadic_to_seq
.
hpp
>
15
#
include
<
userver
/
utils
/
impl
/
internal_tag
.
hpp
>
16
17
USERVER_NAMESPACE_BEGIN
18
19
namespace
utils
::impl {
20
21
struct
RequireSemicolon;
22
23
struct
NonMovable
final
{
24
constexpr
explicit
NonMovable(InternalTag)
noexcept
{}
25
};
26
27
template
<
typename
T>
28
constexpr
auto
IsDefinedAndAggregate() ->
decltype
(
static_cast
<
void
>(
sizeof
(T)),
false
) {
29
return
std::is_aggregate_v<T>;
30
}
31
32
template
<
typename
/*T*/
,
typename
... Args>
33
constexpr
auto
IsDefinedAndAggregate(Args...) ->
bool
{
34
return
false
;
35
}
36
37
template
<
typename
TOwner,
typename
TMember>
38
USERVER_IMPL_NODEBUG_INLINE_FUNC
decltype
(
auto
) ForwardLikeExplicit(TMember& member)
noexcept
{
39
if
constexpr
(std::is_lvalue_reference_v<TOwner> || std::is_lvalue_reference_v<TMember>) {
40
return
member;
41
}
else
{
42
return
std::move(member);
43
}
44
}
45
46
template
<
typename
TOwner,
typename
TMember>
47
USERVER_IMPL_NODEBUG_INLINE_FUNC
decltype
(
auto
) ForwardLikeExplicit(
const
TMember& member)
noexcept
{
48
return
member;
49
}
50
51
}
// namespace utils::impl
52
53
USERVER_NAMESPACE_END
54
55
/// @cond
56
57
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
58
#
define
USERVER_IMPL_STRUCT_MAP
(
r
,
data
,
elem
)
59
USERVER_NAMESPACE
::
utils
::
impl
::
ForwardLikeExplicit
<
OtherDeps
,
decltype
(
other
.
elem
)
>
(
other
.
elem
)
,
60
61
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
62
#
define
USERVER_IMPL_MAKE_FROM_SUPERSET
(
Self
,
...
)
63
template
<
typename
OtherDeps
>
64
static
Self
MakeFromSupersetImpl
(
OtherDeps
&&
other
,
USERVER_NAMESPACE
::
utils
::
impl
::
InternalTag
)
{
65
return
{
BOOST_PP_SEQ_FOR_EACH
(
66
USERVER_IMPL_STRUCT_MAP
,
67
BOOST_PP_EMPTY
(
)
,
68
USERVER_IMPL_VARIADIC_TO_SEQ
(
__VA_ARGS__
)
69
)
}
;
70
}
71
72
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
73
#
define
USERVER_IMPL_STRUCT_SUBSET_MAP
(
r
,
data
,
elem
)
74
/* NOLINTNEXTLINE(bugprone-macro-parentheses) */
75
decltype
(
data
::
elem
)
elem
;
76
77
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
78
#
define
USERVER_IMPL_STRUCT_SUBSET_REF_MAP
(
r
,
data
,
elem
)
79
/* NOLINTNEXTLINE(bugprone-macro-parentheses) */
80
std
::
add_const_t
<
decltype
(
data
::
elem
)
>
&
elem
;
81
82
/// @endcond
83
84
/// @brief Should be invoked inside a manually defined "root" struct to enable
85
/// conversions from it to subset structs created by
86
/// @ref USERVER_DEFINE_STRUCT_SUBSET and @ref USERVER_DEFINE_STRUCT_SUBSET_REF.
87
///
88
/// @hideinitializer
89
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
90
#
define
USERVER_ALLOW_CONVERSIONS_TO_SUBSET
(
)
91
template
<
typename
Other
>
92
requires
(
USERVER_NAMESPACE
::
utils
::
impl
::
IsDefinedAndAggregate
<
Other
>
(
)
)
/*implicit*/
operator
Other
(
)
const
&
{
93
return
Other
::
MakeFromSupersetImpl
(
*
this
,
USERVER_NAMESPACE
::
utils
::
impl
::
InternalTag
{
}
)
;
94
}
95
96
template
<
typename
Other
>
97
requires
(
USERVER_NAMESPACE
::
utils
::
impl
::
IsDefinedAndAggregate
<
Other
>
(
)
)
/*implicit*/
operator
Other
(
)
&&
{
98
return
Other
::
MakeFromSupersetImpl
(
std
::
move
(
*
this
)
,
USERVER_NAMESPACE
::
utils
::
impl
::
InternalTag
{
}
)
;
99
}
100
101
friend
struct
USERVER_NAMESPACE
::
utils
::
impl
::
RequireSemicolon
102
103
/// @brief Defines a struct containing a subset of data members
104
/// from @a OriginalDependencies.
105
///
106
/// Implicit conversions (by copy and by move) are allowed from any superset
107
/// struct to the @a SubsetStruct, as long as the names of the data members
108
/// match, and the superset struct is either defined using
109
/// @ref USERVER_DEFINE_STRUCT_SUBSET or @ref USERVER_DEFINE_STRUCT_SUBSET_REF,
110
/// or it contains @ref USERVER_ALLOW_CONVERSIONS_TO_SUBSET.
111
///
112
/// Usage example:
113
/// @snippet utils/struct_subsets_test.cpp deps definitions
114
/// @snippet utils/struct_subsets_test.cpp deps usage
115
///
116
/// @param SubsetStruct the name of the subset struct to define
117
/// @param OriginalStruct the name of the superset struct, including its
118
/// namespace if needed
119
/// @param ... names of the data members to copy
120
///
121
/// @hideinitializer
122
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
123
#
define
USERVER_DEFINE_STRUCT_SUBSET
(
SubsetStruct
,
OriginalStruct
,
...
)
124
struct
SubsetStruct
{
125
BOOST_PP_SEQ_FOR_EACH
(
126
USERVER_IMPL_STRUCT_SUBSET_MAP
,
127
OriginalStruct
,
128
USERVER_IMPL_VARIADIC_TO_SEQ
(
__VA_ARGS__
)
129
)
130
131
USERVER_IMPL_MAKE_FROM_SUPERSET
(
SubsetStruct
,
__VA_ARGS__
)
132
133
USERVER_ALLOW_CONVERSIONS_TO_SUBSET
(
)
;
134
}
135
136
/// @brief Defines a struct containing a subset of data members
137
/// from @a OriginalDependencies. Appends `const&` to types of all non-reference
138
/// data members.
139
///
140
/// Implicit conversions (by copy and by move) are allowed from any superset
141
/// struct to the @a SubsetStruct, as long as the names of the data members
142
/// match, and the superset struct is either defined using
143
/// @ref USERVER_DEFINE_STRUCT_SUBSET or @ref USERVER_DEFINE_STRUCT_SUBSET_REF,
144
/// or it contains @ref USERVER_ALLOW_CONVERSIONS_TO_SUBSET.
145
///
146
/// `*Ref` structs can be used for parameters of utility functions to avoid
147
/// copying non-reference data members.
148
///
149
/// Usage example:
150
/// @snippet utils/struct_subsets_test.cpp ref definitions
151
/// @snippet utils/struct_subsets_test.cpp ref usage
152
///
153
/// @param SubsetStructRef the name of the subset struct to define, it should
154
/// typically contain `*Ref` suffix to underline that it needs the original
155
/// backing struct to work
156
/// @param OriginalStruct the name of the superset struct, including its
157
/// namespace if needed
158
/// @param ... names of the data members to copy
159
///
160
/// @hideinitializer
161
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
162
#
define
USERVER_DEFINE_STRUCT_SUBSET_REF
(
SubsetStructRef
,
OriginalStruct
,
...
)
163
struct
SubsetStructRef
{
164
BOOST_PP_SEQ_FOR_EACH
(
165
USERVER_IMPL_STRUCT_SUBSET_REF_MAP
,
166
OriginalStruct
,
167
USERVER_IMPL_VARIADIC_TO_SEQ
(
__VA_ARGS__
)
168
)
169
170
/* Protects against copying into async functions */
171
USERVER_NAMESPACE
::
utils
::
impl
::
NonMovable
_impl_non_movable
{
USERVER_NAMESPACE
::
utils
::
impl
::
InternalTag
{
}
}
;
172
173
USERVER_IMPL_MAKE_FROM_SUPERSET
(
SubsetStructRef
,
__VA_ARGS__
)
174
175
USERVER_ALLOW_CONVERSIONS_TO_SUBSET
(
)
;
176
}
userver
utils
struct_subsets.hpp
Generated on
for userver by
Doxygen
1.17.0