Cppgres
Build Postgres extensions in C++
Loading...
Searching...
No Matches
utils.hpp
Go to the documentation of this file.
1
4#pragma once
5
6#include <optional>
7#include <string_view>
8#include <tuple>
9#include <utility>
10
11#include "pfr.hpp"
12#define CPPGRES_USE_BOOST_PFR 1
13/*
14// This has been commented out while Boost.PFR is embedded with Cppgres
15
16#if __has_include(<boost/pfr.hpp>)
17#include <boost/pfr.hpp>
18#define CPPGRES_USE_BOOST_PFR 1
19#else
20#define CPPGRES_USE_BOOST_PFR 0
21#endif
22*/
23namespace cppgres::utils {
24
25// Primary template: if T is not an optional, just yield T.
26template <typename T> struct remove_optional {
27 using type = T;
28};
29
30// Partial specialization for std::optional.
31template <typename T> struct remove_optional<std::optional<T>> {
32 using type = T;
33};
34
35// Convenience alias template.
36template <typename T> using remove_optional_t = typename utils::remove_optional<T>::type;
37
38template <typename T>
39concept is_optional =
40 requires { typename T::value_type; } && std::same_as<T, std::optional<typename T::value_type>>;
41
42template <typename T> constexpr std::string_view type_name() {
43#ifdef __clang__
44 constexpr std::string_view p = __PRETTY_FUNCTION__;
45 constexpr std::string_view key = "T = ";
46 const auto start = p.find(key) + key.size();
47 const auto end = p.find(']', start);
48 return p.substr(start, end - start);
49#elif defined(__GNUC__)
50 constexpr std::string_view p = __PRETTY_FUNCTION__;
51 constexpr std::string_view key = "T = ";
52 const auto start = p.find(key) + key.size();
53 const auto end = p.find(';', start);
54 return p.substr(start, end - start);
55#elif defined(_MSC_VER)
56 constexpr std::string_view p = __FUNCSIG__;
57 constexpr std::string_view key = "type_name<";
58 const auto start = p.find(key) + key.size();
59 const auto end = p.find(">(void)");
60 return p.substr(start, end - start);
61#else
62 return "Unsupported compiler";
63#endif
64}
65
66template <typename T, typename = void> struct tuple_traits_impl {
67 using tuple_size_type = std::integral_constant<std::size_t, 1>;
68
69 template <std::size_t I, typename U = T> static constexpr decltype(auto) get(U &&t) noexcept {
70 return std::forward<U>(t);
71 }
72
74 using type = T;
75 };
76
77 template <std::size_t I> using tuple_element = tuple_element_t;
78};
79
80// Primary implementation: for types that already have a tuple-like interface
81template <typename T>
82struct tuple_traits_impl<T, std::void_t<decltype(std::tuple_size<T>::value)>> {
83 using tuple_size_type = std::tuple_size<T>;
84
85 template <std::size_t I, typename U = T> static constexpr decltype(auto) get(U &&t) noexcept {
86 return std::get<I>(std::forward<U>(t));
87 }
88
89 template <std::size_t I> using tuple_element = std::tuple_element<I, T>;
90};
91
92// Specialization: for aggregates that Boost.PFR can handle.
93// This specialization is enabled if the type is an aggregate
94#if CPPGRES_USE_BOOST_PFR
95template <typename T> struct tuple_traits_impl<T, std::enable_if_t<std::is_aggregate_v<T>>> {
96 using tuple_size_type = boost::pfr::tuple_size<T>;
97
98 template <std::size_t I, typename U = T> static constexpr decltype(auto) get(U &&t) noexcept {
99 return boost::pfr::get<I>(std::forward<U>(t));
100 }
101
102 template <std::size_t I> using tuple_element = boost::pfr::tuple_element<I, T>;
103};
104
105#endif
106
107template <typename T> using tuple_size = typename tuple_traits_impl<T>::tuple_size_type;
108
109template <typename T> constexpr std::size_t tuple_size_v = tuple_size<T>::value;
110
111template <std::size_t I, typename T>
112using tuple_element = typename tuple_traits_impl<T>::template tuple_element<I>;
113
114template <std::size_t I, typename T> using tuple_element_t = typename tuple_element<I, T>::type;
115
116template <std::size_t I, typename T> constexpr decltype(auto) get(T &&t) noexcept {
118 std::forward<T>(t));
119}
120
121template <typename T> struct is_std_tuple : std::false_type {};
122
123template <typename... Ts> struct is_std_tuple<std::tuple<Ts...>> : std::true_type {};
124
125template <typename T>
126concept std_tuple = is_std_tuple<T>::value;
127
128template <typename T> decltype(auto) tie(T &val) {
129#if CPPGRES_USE_BOOST_PFR == 1
130 if constexpr (std::is_aggregate_v<T>) {
131 return boost::pfr::structure_tie(val);
132 } else
133#endif
134 if constexpr (std_tuple<T>) {
135 return val;
136 } else {
137 return std::tuple(val);
138 }
139}
140
141} // namespace cppgres::utils
Definition: utils.hpp:39
Definition: utils.hpp:126
Definition: utils.hpp:121
Definition: utils.hpp:26
Definition: utils.hpp:66