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<>>
45template <typename T>
46inline constexpr bool kIsMappedToPg = IsMappedToPg<T>::value;
47
48/// @brief Mark C++ mapping a special case for disambiguation.
49template <typename T, typename = USERVER_NAMESPACE::utils::void_t<>>
50struct IsSpecialMapping : std::false_type {};
51template <typename T>
52inline constexpr bool kIsSpecialMapping = IsSpecialMapping<T>::value;
53//@}
54
55//@{
56/** @name Detect iostream operators */
57template <typename T, typename = USERVER_NAMESPACE::utils::void_t<>>
58struct HasOutputOperator : std::false_type {};
59
60template <typename T>
62 T,
63 USERVER_NAMESPACE::utils::void_t<decltype(std::declval<std::ostream&>() << std::declval<T&>())>> : std::true_type {
64};
65
66template <typename T, typename = USERVER_NAMESPACE::utils::void_t<>>
67struct HasInputOperator : std::false_type {};
68
69template <typename T>
70struct HasInputOperator<
71 T,
72 USERVER_NAMESPACE::utils::void_t<decltype(std::declval<std::istream&>() >> std::declval<T&>())>> : std::true_type {
73};
74//@}
75
76//@{
77/** @name Traits for containers */
78/// @brief Mark C++ container type as supported by the driver.
79template <typename T>
80struct IsCompatibleContainer : std::false_type {};
81template <typename T>
82inline constexpr bool kIsCompatibleContainer = IsCompatibleContainer<T>::value;
83
84template <typename T>
85inline constexpr bool kIsFixedSizeContainer = meta::kIsFixedSizeContainer<T>;
86
87//@{
88/// @brief Calculate number of dimensions in C++ container.
89template <typename T, typename Enable = USERVER_NAMESPACE::utils::void_t<>>
90struct DimensionCount : SizeConstant<0> {};
91
92template <typename T>
94 : SizeConstant<1 + DimensionCount<typename T::value_type>::value> {};
95template <typename T>
96inline constexpr std::size_t kDimensionCount = DimensionCount<T>::value;
97//@}
98
99//@{
100/// @brief Detect type of multidimensional C++ container.
101template <typename T>
102struct ContainerFinalElement;
103
104namespace detail {
105
106template <typename T>
107struct FinalElementImpl {
108 using type = T;
109};
110
111template <typename T>
112struct ContainerFinalElementImpl {
113 using type = typename ContainerFinalElement<typename T::value_type>::type;
114};
115
116} // namespace detail
117
118template <typename T>
119struct ContainerFinalElement
120 : std::conditional_t<kIsCompatibleContainer<T>, detail::ContainerFinalElementImpl<T>, detail::FinalElementImpl<T>> {
121};
122
123template <typename T>
124using ContainerFinaleElementType = typename ContainerFinalElement<T>::type;
125//@}
126
127//@{
128/** @name IsMappedToArray implementation */
129namespace detail {
130
131template <typename Container>
132constexpr bool EnableContainerMapping() {
133 if constexpr (!traits::kIsCompatibleContainer<Container>) {
134 return false;
135 } else {
136 return traits::kIsMappedToPg<typename traits::ContainerFinalElement<Container>::type>;
137 }
138}
139
140} // namespace detail
141
142template <typename T>
143struct IsMappedToArray : BoolConstant<detail::EnableContainerMapping<T>()> {};
144
145//@}
146
147template <typename T, typename = USERVER_NAMESPACE::utils::void_t<>>
148struct CanReserve : std::false_type {};
149template <typename T>
150struct CanReserve<T, USERVER_NAMESPACE::utils::void_t<decltype(std::declval<T>().reserve(std::declval<std::size_t>()))>>
151 : std::true_type {};
152template <typename T>
153inline constexpr bool kCanReserve = CanReserve<T>::value;
154
155template <typename T, typename = USERVER_NAMESPACE::utils::void_t<>>
156struct CanResize : std::false_type {};
157
158template <typename T>
159struct CanResize<T, USERVER_NAMESPACE::utils::void_t<decltype(std::declval<T>().resize(std::declval<std::size_t>()))>>
160 : std::true_type {};
161template <typename T>
162inline constexpr bool kCanResize = CanResize<T>::value;
163
164template <typename T, typename = USERVER_NAMESPACE::utils::void_t<>>
165struct CanClear : std::false_type {};
166
167template <typename T>
168struct CanClear<T, USERVER_NAMESPACE::utils::void_t<decltype(std::declval<T>().clear())>> : std::true_type {};
169template <typename T>
170inline constexpr bool kCanClear = CanClear<T>::value;
171
172template <typename T>
173auto Inserter(T& container) {
174 return meta::Inserter(container);
175}
176//@}
177
178template <typename T>
179struct RemoveTupleReferences;
180
181template <typename... T>
182struct RemoveTupleReferences<std::tuple<T...>> {
183 using type = std::tuple<std::remove_reference_t<T>...>;
184};
185
186template <typename T>
187struct IsTupleOfRefs : std::false_type {};
188template <typename... T>
189struct IsTupleOfRefs<std::tuple<T&...>> : std::true_type {};
190
191template <typename T>
192struct AddTupleConstRef;
193
194template <typename... T>
195struct AddTupleConstRef<std::tuple<T...>> {
196 using type = std::tuple<std::add_const_t<std::add_lvalue_reference_t<std::decay_t<T>>>...>;
197};
198
199template <typename Tuple>
200struct TupleHasParsers;
201
202template <typename... T>
203struct TupleHasParsers<std::tuple<T...>> : std::bool_constant<(HasParser<std::decay_t<T>>::value && ...)> {};
204
205template <typename Tuple>
206struct TupleHasFormatters;
207
208template <typename... T>
209struct TupleHasFormatters<std::tuple<T...>> : std::bool_constant<(HasFormatter<std::decay_t<T>>::value && ...)> {};
210
211//@}
212
213//@{
214/** @name Type mapping traits */
215//@}
216
217} // namespace storages::postgres::io::traits
218
219USERVER_NAMESPACE_END