OZO 「お象」
Boost.Asio and libpq based asynchronous PostgreSQL unofficial header-only C++17 client library.
type_traits.h
1 #pragma once
2 
3 #include <ozo/detail/float.h>
4 #include <ozo/core/strong_typedef.h>
5 #include <ozo/core/nullable.h>
6 #include <ozo/core/unwrap.h>
7 #include <ozo/core/concept.h>
8 #include <ozo/optional.h>
9 
10 #include <libpq-fe.h>
11 
12 #include <boost/hana/at_key.hpp>
13 #include <boost/hana/insert.hpp>
14 #include <boost/hana/string.hpp>
15 #include <boost/hana/map.hpp>
16 #include <boost/hana/pair.hpp>
17 #include <boost/hana/type.hpp>
18 #include <boost/hana/not_equal.hpp>
19 
20 #include <memory>
21 #include <string>
22 #include <string_view>
23 #include <vector>
24 #include <type_traits>
25 
60 namespace ozo {
61 
62 namespace hana = boost::hana;
63 using namespace hana::literals;
64 
65 namespace fusion = boost::fusion;
70 using oid_t = ::Oid;
71 
82 template <oid_t Oid>
83 struct oid_constant : std::integral_constant<oid_t, Oid> {};
84 
90 
95 inline constexpr null_oid_t null_oid;
96 
97 template <typename T>
98 struct is_array : std::false_type {};
99 
149 template <typename T>
151 inline constexpr auto Array = is_array<std::decay_t<T>>::value;
153 
154 namespace definitions {
155 template <typename T>
156 struct type;
157 
158 template <typename T>
159 struct array;
160 } // namespace definitions
161 
162 namespace detail {
163 
164 template <typename Traits, typename = std::void_t<>>
165 struct is_type_traits_defined : std::false_type {};
166 
167 template <typename T>
168 struct is_type_traits_defined<T, Require<
169  !std::is_void_v<typename T::name>
170 >> : std::true_type {};
171 
172 template <typename T>
173 inline auto get_type_traits(const T&) {
174  using type = unwrap_type<T>;
175  if constexpr (Array<type>) {
176  using value_type = unwrap_type<typename type::value_type>;
177  if constexpr (is_type_traits_defined<definitions::array<value_type>>::value) {
178  return definitions::array<value_type>{};
179  } else {
180  return;
181  }
182  } else {
183  if constexpr (is_type_traits_defined<definitions::type<type>>::value) {
184  return definitions::type<type>{};
185  } else {
186  return;
187  }
188  }
189 }
190 
191 } // namespace detail
192 
206 #ifdef OZO_DOCUMENTATION
207 template <typename T>
208 struct type_traits {
209  using name = <implementation defined>;
210  using oid = <implementation defined>;
211  using size = <implementation defined>;
212 };
213 #endif
214 
215 template <typename T>
216 using type_traits = decltype(detail::get_type_traits(std::declval<T>()));
217 
224 template <typename T>
226 inline constexpr auto HasDefinition = !std::is_void_v<type_traits<T>>;
228 
229 template <typename T>
230 struct is_composite : std::bool_constant<
231  HanaStruct<T> || FusionAdaptedStruct<T>
232 > {};
233 
256 template <typename T>
258 inline constexpr auto Composite = is_composite<std::decay_t<T>>::value;
260 
265 using size_type = std::int32_t;
266 
277 template <size_type n>
278 struct size_constant : std::integral_constant<size_type, n> {};
279 
280 inline constexpr size_constant<-1> null_state_size;
281 
287 template <size_type n>
288 using bytes = size_constant<n>;
289 struct dynamic_size : size_constant<-1> {};
290 
291 template <typename T, typename = std::void_t<>>
292 struct is_built_in : std::false_type {};
293 
294 template <typename T>
295 struct is_built_in<T, std::enable_if_t<
296  !std::is_void_v<typename type_traits<T>::oid>>
297 > : std::true_type {};
298 
305 template <typename T>
306 inline constexpr bool BuiltIn = is_built_in<std::decay_t<T>>::value;
307 
308 template <typename T>
309 struct is_dynamic_size : std::is_same<typename type_traits<T>::size, dynamic_size> {};
310 
317 template <typename T>
318 inline constexpr auto DynamicSize = is_dynamic_size<std::decay_t<T>>::value;
319 
326 template <typename T>
327 inline constexpr auto StaticSize = !DynamicSize<T>;
328 
335 template <typename T>
336 constexpr auto type_name() noexcept {
337  static_assert(!std::is_void_v<type_traits<T>>,
338  "no type_traits found for the type");
339  constexpr auto name = typename type_traits<T>::name{};
340  constexpr char const* retval = hana::to<char const*>(name);
341  return retval;
342 }
343 
350 template <typename T>
351 constexpr auto type_name(const T&) noexcept {return type_name<T>();}
352 
353 namespace detail {
354 
355 template <typename Name, typename Oid = void, typename Size = dynamic_size>
356 struct type_definition {
357  using name = Name;
358  using oid = Oid;
359  using size = Size;
360 };
361 
362 template <typename Type, typename Oid>
363 using array_definition = type_definition<
364  decltype(typename type_traits<Type>::name{} + "[]"_s),
365  Oid
366 >;
367 
368 } // namespace detail
369 } // namespace ozo
370 
371 #define OZO_PG_DEFINE_TYPE_(Type, Name, OidType, Size) \
372  namespace ozo::definitions {\
373  template <>\
374  struct type<Type> : detail::type_definition<decltype(Name##_s), OidType, Size>{\
375  static_assert(std::is_same_v<Size, dynamic_size>\
376  || Size::value == null_state_size\
377  || static_cast<size_type>(sizeof(Type)) == Size::value,\
378  #Type " type size does not match to declared size");\
379  };\
380  }
381 
382 #define OZO_PG_DEFINE_TYPE(Type, Name, Oid, Size) \
383  OZO_PG_DEFINE_TYPE_(Type, Name, oid_constant<Oid>, Size)
384 
385 #define OZO_PG_DEFINE_TYPE_ARRAY_(Type, OidType) \
386  namespace ozo::definitions {\
387  template <>\
388  struct array<Type> : detail::array_definition<Type, OidType>{};\
389  }
390 
391 #define OZO_PG_DEFINE_TYPE_AND_ARRAY_(Type, Name, OidType, ArrayOidType, Size) \
392  OZO_PG_DEFINE_TYPE_(Type, Name, OidType, Size) \
393  OZO_PG_DEFINE_TYPE_ARRAY_(Type, ArrayOidType)
394 
414 #ifdef OZO_DOCUMENTATION
415 #define OZO_PG_DEFINE_TYPE_AND_ARRAY(Type, Name, Oid, ArrayOid, Size)
416 #else
417 #define OZO_PG_DEFINE_TYPE_AND_ARRAY(Type, Name, Oid, ArrayOid, Size) \
418  OZO_PG_DEFINE_TYPE_AND_ARRAY_(Type, Name, oid_constant<Oid>, oid_constant<ArrayOid>, Size)
419 #endif
420 
454 #ifdef OZO_DOCUMENTATION
455 #define OZO_PG_DEFINE_CUSTOM_TYPE(Type, Name [, Size])
456 #else
457 #define OZO_PG_DEFINE_CUSTOM_TYPE_IMPL_3(Type, Name, Size) \
458  OZO_PG_DEFINE_TYPE_AND_ARRAY_(Type, Name, void, void, Size)
459 
460 #define OZO_PG_DEFINE_CUSTOM_TYPE_IMPL_2(Type, Name) \
461  OZO_PG_DEFINE_CUSTOM_TYPE_IMPL_3(Type, Name, dynamic_size)
462 
463 #define OZO_PG_DEFINE_CUSTOM_TYPE(...)\
464  BOOST_PP_OVERLOAD(OZO_PG_DEFINE_CUSTOM_TYPE_IMPL_,__VA_ARGS__)(__VA_ARGS__)
465 #endif
466 
467 namespace ozo {
468 
469 namespace detail {
470 
471 template <typename ... T>
472 constexpr decltype(auto) register_types() noexcept {
473  return hana::make_map(
474  hana::make_pair(hana::type_c<T>, null_oid()) ...
475  );
476 }
477 
478 } // namespace detail
479 
486 template <typename ...Ts>
487 struct oid_map_t {
488  using impl_type = decltype(detail::register_types<Ts...>());
489 
490  impl_type impl;
491 };
492 
493 
494 template <typename T>
495 struct is_oid_map : std::false_type {};
496 
497 template <typename ...Ts>
498 struct is_oid_map<oid_map_t<Ts...>> : std::true_type {};
499 
533 template <typename T>
534 inline constexpr auto OidMap = is_oid_map<std::decay_t<T>>::value;
535 
561 template <typename ...Ts>
562 constexpr oid_map_t<Ts...> register_types() noexcept {
563  return {};
564 }
565 
570 using empty_oid_map = std::decay_t<decltype(register_types<>())>;
571 
572 inline constexpr empty_oid_map empty_oid_map_c;
573 
581 template <typename T, typename ...Ts>
582 inline void set_type_oid(oid_map_t<Ts...>& map, oid_t oid) noexcept {
583  static_assert(!is_built_in<T>::value, "type must not be built-in");
584  map.impl[hana::type_c<T>] = oid;
585 }
586 
594 #ifdef OZO_DOCUMENTATION
595 template <typename T, typename OidMap>
596 oid_t type_oid(const OidMap& map) noexcept;
597 #else
598 template <typename T, typename ...Ts>
599 inline auto type_oid(const oid_map_t<Ts...>& map) noexcept
601  constexpr auto key = hana::type_c<unwrap_type<T>>;
602  static_assert(decltype(hana::find(map.impl, key) != hana::nothing)::value,
603  "type OID for T can not be found in the OidMap, it should be registered via register_type()");
604  return map.impl[key];
605 }
606 
607 template <typename T, typename OidMap>
608 constexpr auto type_oid(const OidMap&) noexcept
609  -> Require<BuiltIn<T>, oid_t> {
610  static_assert(ozo::OidMap<OidMap>, "map should model OidMap concept");
611  return typename type_traits<T>::oid();
612 }
613 #endif
614 
622 #ifdef OZO_DOCUMENTATION
623 template <typename T, typename OidMap>
624 oid_t type_oid(const OidMap& map, const T& v) noexcept
625 #else
626 template <typename T, typename OidMap>
627 inline auto type_oid(const OidMap& map, const T&) noexcept{
628  static_assert(ozo::OidMap<OidMap>, "map should model OidMap concept");
629  return type_oid<std::decay_t<T>>(map);
630 }
631 #endif
632 
641 template <typename T, typename OidMap>
642 inline bool accepts_oid(const OidMap& map, oid_t oid) noexcept {
643  static_assert(ozo::OidMap<OidMap>, "map should model OidMap concept");
644  return type_oid<T>(map) == oid;
645 }
646 
655 template <typename T, typename OidMap>
656 inline bool accepts_oid(const OidMap& map, const T& , oid_t oid) noexcept {
657  return accepts_oid<std::decay_t<T>>(map, oid);
658 }
659 
673 template <typename ...Ts>
674 inline constexpr bool empty(const oid_map_t<Ts...>& map) noexcept {
675  return hana::length(map.impl) == hana::size_c<0>;
676 }
677 
678 } // namespace ozo
HasDefinition
Condition indicates if type has corresponding type traits for PostgreSQL.
ozo::BuiltIn
constexpr bool BuiltIn
Condition indicates if the specified type is built-in for PG.
Definition: type_traits.h:306
ozo::size_constant
Object size constant type.
Definition: type_traits.h:278
ozo::null_oid
constexpr null_oid_t null_oid
Constant for empty OID.
Definition: type_traits.h:95
ozo::set_type_oid
void set_type_oid(oid_map_t< Ts... > &map, oid_t oid) noexcept
Definition: type_traits.h:582
Array
Array concept represents PostgreSQL array.
ozo::DynamicSize
constexpr auto DynamicSize
Condition indicates if the specified type is has dynamic size.
Definition: type_traits.h:318
ozo::OidMap
constexpr auto OidMap
Map of C++ types to corresponding PostgreSQL types OIDs.
Definition: type_traits.h:534
ozo::empty
constexpr bool empty(const oid_map_t< Ts... > &map) noexcept
Definition: type_traits.h:674
ozo::register_types
constexpr oid_map_t< Ts... > register_types() noexcept
Provides #OidMap implementation for user-defined types.
Definition: type_traits.h:562
Composite
Composite concept represents PostgreSQL composite types.
ozo::type_traits::oid
< implementation defined > oid
ozo::oid_constant with Oid of the built-in type or null_oid_t for non built-in type
Definition: type_traits.h:210
ozo::type_traits::name
< implementation defined > name
boost::hana::string with name of the type in a database
Definition: type_traits.h:209
ozo::Require
Type Require
Concept requirement emulation.
Definition: concept.h:54
ozo::type_traits
Type traits template forward declaration.
Definition: type_traits.h:208
ozo::size_type
std::int32_t size_type
PostgreSQL size type.
Definition: type_traits.h:265
ozo::value
Database request result value proxy.
Definition: result.h:25
ozo::oid_constant
OID constant type.
Definition: type_traits.h:83
ozo::accepts_oid
bool accepts_oid(const OidMap &map, const T &, oid_t oid) noexcept
Definition: type_traits.h:656
ozo::type_traits::size
< implementation defined > size
ozo::size_constant with size of the type object in bytes or ozo::dynamic_size in other case
Definition: type_traits.h:211
ozo::type_oid
oid_t type_oid(const OidMap &map, const T &v) noexcept template< typename T
Function returns oid for type from #OidMap.
ozo::oid_map_t
OidMap implementation type.
Definition: type_traits.h:487
ozo::empty_oid_map
std::decay_t< decltype(register_types<>())> empty_oid_map
Type alias for empty #OidMap.
Definition: type_traits.h:570
ozo::type_name
constexpr auto type_name(const T &) noexcept
Function returns type name in Postgre SQL.
Definition: type_traits.h:351
ozo::oid_t
::Oid oid_t
PostgreSQL OID type - object identifier.
Definition: type_traits.h:70
ozo::StaticSize
constexpr auto StaticSize
Condition indicates if the specified type is has fixed size.
Definition: type_traits.h:327