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>
18using BoolConstant = std::bool_constant<Value>;
19template <std::size_t Value>
20using SizeConstant = std::integral_constant<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>
26concept IsMappedToSystemType = utils::IsDeclComplete<CppToSystemPg<T>>::value;
27
28/// @brief Detect if the C++ type is mapped to a Postgres user type.
29template <typename T>
30concept IsMappedToUserType = utils::IsDeclComplete<CppToUserPg<T>>::value;
31
32namespace detail {
33
34template <typename Container>
35constexpr bool EnableContainerMapping() noexcept;
36
37} // namespace detail
38
39/// @brief Detect if the C++ type is mapped to a Postgres array type.
40template <typename T>
41concept IsMappedToArray = detail::EnableContainerMapping<T>();
42
43/// @brief Detect if the C++ type is mapped to a Postgres type.
44template <typename T>
46template <typename T>
47concept kIsMappedToPg = IsMappedToPg<T>::value; // NOLINT(readability-identifier-naming)
48
49/// @brief Mark C++ mapping a special case for disambiguation.
50template <typename T>
51struct IsSpecialMapping : std::false_type {};
52///@}
53
54///@{
55/** @name Traits for containers */
56/// @brief Mark C++ container type as supported by the driver.
57template <typename T>
58struct IsCompatibleContainer : std::false_type {};
59template <typename T>
60concept kIsCompatibleContainer = IsCompatibleContainer<T>::value; // NOLINT(readability-identifier-naming)
61/// @}
62
63///@{
64/// @brief Calculate number of dimensions in C++ container.
65template <typename T>
66struct DimensionCount : SizeConstant<0> {};
67
68template <kIsCompatibleContainer T>
69struct DimensionCount<T> : SizeConstant<1 + DimensionCount<typename T::value_type>::value> {};
70template <typename T>
71inline constexpr std::size_t kDimensionCount = DimensionCount<T>::value;
72///@}
73
74///@{
75/// @brief Detect type of multidimensional C++ container.
76template <typename T>
78
79namespace detail {
80
81template <typename T>
82struct FinalElementImpl {
83 using type = T;
84};
85
86template <typename T>
87struct ContainerFinalElementImpl {
88 using type = typename ContainerFinalElement<typename T::value_type>::type;
89};
90
91} // namespace detail
92
93template <typename T>
95 : std::conditional_t<kIsCompatibleContainer<T>, detail::ContainerFinalElementImpl<T>, detail::FinalElementImpl<T>> {
96};
97
98template <typename T>
99using ContainerFinaleElementType = typename ContainerFinalElement<T>::type;
100///@}
101
102namespace detail {
103
104template <typename Container>
105constexpr bool EnableContainerMapping() noexcept {
106 if constexpr (!traits::kIsCompatibleContainer<Container>) {
107 return false;
108 } else {
109 return traits::kIsMappedToPg<typename traits::ContainerFinalElement<Container>::type>;
110 }
111}
112
113} // namespace detail
114
115template <typename T>
116concept CanReserve = requires(T value) { value.reserve(std::size_t{1}); };
117
118template <typename T>
119concept CanResize = requires(T value) { value.resize(std::size_t{1}); };
120
121template <typename T>
122concept CanClear = requires(T value) { value.clear(); };
123
124template <typename T>
125auto Inserter(T& container) {
126 return meta::Inserter(container);
127}
128
129template <typename T>
131
132template <typename... T>
133struct RemoveTupleReferences<std::tuple<T...>> {
134 using type = std::tuple<std::remove_reference_t<T>...>;
135};
136
137template <typename T>
138struct IsTupleOfRefs : std::false_type {};
139template <typename... T>
140struct IsTupleOfRefs<std::tuple<T&...>> : std::true_type {};
141
142template <typename T>
144
145template <typename... T>
146struct AddTupleConstRef<std::tuple<T...>> {
147 using type = std::tuple<const std::remove_reference_t<T>&...>;
148};
149
150template <typename Tuple>
152
153template <typename... T>
154struct TupleHasParsers<std::tuple<T...>> : std::bool_constant<(HasParser<std::remove_cvref_t<T>> && ...)> {};
155
156template <typename Tuple>
158
159template <typename... T>
160struct TupleHasFormatters<std::tuple<T...>> : std::bool_constant<(HasFormatter<std::remove_cvref_t<T>> && ...)> {};
161
162} // namespace storages::postgres::io::traits
163
164USERVER_NAMESPACE_END