userver: userver/storages/postgres/io/type_traits.hpp Source File
Loading...
Searching...
No Matches
type_traits.hpp
1#pragma once
2
3#include <iosfwd>
4#include <tuple>
5#include <type_traits>
6
7#include <userver/utils/meta.hpp>
8
9#include <userver/storages/postgres/detail/is_decl_complete.hpp>
10#include <userver/storages/postgres/io/io_fwd.hpp>
11#include <userver/storages/postgres/io/traits.hpp>
12
13USERVER_NAMESPACE_BEGIN
14
15namespace storages::postgres::io::traits {
16
17template <bool Value>
19template <std::size_t Value>
21
22//@{
23/** @name Type mapping traits */
24/// @brief Detect if the C++ type is mapped to a Postgres system type.
25template <typename T>
27template <typename T>
28inline constexpr bool kIsMappedToSystemType = IsMappedToSystemType<T>::value;
29
30/// @brief Detect if the C++ type is mapped to a Postgres user type.
31template <typename T>
33template <typename T>
34inline constexpr bool kIsMappedToUserType = IsMappedToUserType<T>::value;
35
36/// @brief Detect if the C++ type is mapped to a Postgres array type.
37template <typename T>
38struct IsMappedToArray;
39template <typename T>
40inline constexpr bool kIsMappedToArray = IsMappedToArray<T>::value;
41
42/// @brief Detect if the C++ type is mapped to a Postgres type.
43template <typename T, typename = USERVER_NAMESPACE::utils::void_t<>>
44struct IsMappedToPg
47template <typename T>
48inline constexpr bool kIsMappedToPg = IsMappedToPg<T>::value;
49
50/// @brief Mark C++ mapping a special case for disambiguation.
51template <typename T, typename = USERVER_NAMESPACE::utils::void_t<>>
53template <typename T>
54inline constexpr bool kIsSpecialMapping = IsSpecialMapping<T>::value;
55//@}
56
57//@{
58/** @name Detect iostream operators */
59template <typename T, typename = USERVER_NAMESPACE::utils::void_t<>>
61
62template <typename T>
64 T, USERVER_NAMESPACE::utils::void_t<decltype(std::declval<std::ostream&>()
65 << std::declval<T&>())>>
66 : std::true_type {};
67
68template <typename T, typename = USERVER_NAMESPACE::utils::void_t<>>
70
71template <typename T>
72struct HasInputOperator<
73 T, USERVER_NAMESPACE::utils::void_t<
74 decltype(std::declval<std::istream&>() >> std::declval<T&>())>>
75 : std::true_type {};
76//@}
77
78//@{
79/** @name Traits for containers */
80/// @brief Mark C++ container type as supported by the driver.
81template <typename T>
83template <typename T>
84inline constexpr bool kIsCompatibleContainer = IsCompatibleContainer<T>::value;
85
86template <typename T>
87inline constexpr bool kIsFixedSizeContainer = meta::kIsFixedSizeContainer<T>;
88
89//@{
90/// @brief Calculate number of dimensions in C++ container.
91template <typename T, typename Enable = USERVER_NAMESPACE::utils::void_t<>>
92struct DimensionCount : SizeConstant<0> {};
93
94template <typename T>
96 : SizeConstant<1 + DimensionCount<typename T::value_type>::value> {};
97template <typename T>
98inline constexpr std::size_t kDimensionCount = DimensionCount<T>::value;
99//@}
100
101//@{
102/// @brief Detect type of multidimensional C++ container.
103template <typename T>
104struct ContainerFinalElement;
105
106namespace detail {
107
108template <typename T>
109struct FinalElementImpl {
110 using type = T;
111};
112
113template <typename T>
114struct ContainerFinalElementImpl {
115 using type = typename ContainerFinalElement<typename T::value_type>::type;
116};
117
118} // namespace detail
119
120template <typename T>
121struct ContainerFinalElement
122 : std::conditional_t<kIsCompatibleContainer<T>,
123 detail::ContainerFinalElementImpl<T>,
124 detail::FinalElementImpl<T>> {};
125
126template <typename T>
127using ContainerFinaleElementType = typename ContainerFinalElement<T>::type;
128//@}
129
130//@{
131/** @name IsMappedToArray implementation */
132namespace detail {
133
134template <typename Container>
135constexpr bool EnableContainerMapping() {
136 if constexpr (!traits::kIsCompatibleContainer<Container>) {
137 return false;
138 } else {
139 return traits::kIsMappedToPg<
140 typename traits::ContainerFinalElement<Container>::type>;
141 }
142}
143
144} // namespace detail
145
146template <typename T>
147struct IsMappedToArray : BoolConstant<detail::EnableContainerMapping<T>()> {};
148
149//@}
150
151template <typename T, typename = USERVER_NAMESPACE::utils::void_t<>>
152struct CanReserve : std::false_type {};
153template <typename T>
154struct CanReserve<
155 T, USERVER_NAMESPACE::utils::void_t<decltype(std::declval<T>().reserve(
156 std::declval<std::size_t>()))>> : std::true_type {};
157template <typename T>
158inline constexpr bool kCanReserve = CanReserve<T>::value;
159
160template <typename T, typename = USERVER_NAMESPACE::utils::void_t<>>
161struct CanResize : std::false_type {};
162
163template <typename T>
164struct CanResize<
165 T, USERVER_NAMESPACE::utils::void_t<decltype(std::declval<T>().resize(
166 std::declval<std::size_t>()))>> : std::true_type {};
167template <typename T>
168inline constexpr bool kCanResize = CanResize<T>::value;
169
170template <typename T, typename = USERVER_NAMESPACE::utils::void_t<>>
171struct CanClear : std::false_type {};
172
173template <typename T>
174struct CanClear<
175 T, USERVER_NAMESPACE::utils::void_t<decltype(std::declval<T>().clear())>>
176 : std::true_type {};
177template <typename T>
178inline constexpr bool kCanClear = CanClear<T>::value;
179
180template <typename T>
181auto Inserter(T& container) {
182 return meta::Inserter(container);
183}
184//@}
185
186template <typename T>
187struct RemoveTupleReferences;
188
189template <typename... T>
190struct RemoveTupleReferences<std::tuple<T...>> {
191 using type = std::tuple<std::remove_reference_t<T>...>;
192};
193
194template <typename T>
195struct IsTupleOfRefs : std::false_type {};
196template <typename... T>
197struct IsTupleOfRefs<std::tuple<T&...>> : std::true_type {};
198
199template <typename T>
200struct AddTupleConstRef;
201
202template <typename... T>
203struct AddTupleConstRef<std::tuple<T...>> {
204 using type = std::tuple<
205 std::add_const_t<std::add_lvalue_reference_t<std::decay_t<T>>>...>;
206};
207
208template <typename Tuple>
209struct TupleHasParsers;
210
211template <typename... T>
212struct TupleHasParsers<std::tuple<T...>>
213 : std::bool_constant<(HasParser<std::decay_t<T>>::value && ...)> {};
214
215template <typename Tuple>
216struct TupleHasFormatters;
217
218template <typename... T>
219struct TupleHasFormatters<std::tuple<T...>>
220 : std::bool_constant<(HasFormatter<std::decay_t<T>>::value && ...)> {};
221
222//@}
223
224//@{
225/** @name Type mapping traits */
226//@}
227
228} // namespace storages::postgres::io::traits
229
230USERVER_NAMESPACE_END