Dash Core Source Documentation (0.16.0.1)

Find detailed information regarding the Dash Core source code.

combine_standard_layout.hpp
Go to the documentation of this file.
1 //
2 // immer: immutable data structures for C++
3 // Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
4 //
5 // This software is distributed under the Boost Software License, Version 1.0.
6 // See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
7 //
8 
9 #pragma once
10 
11 #include <type_traits>
12 
13 #if __GNUC__ == 7 || __GNUC_MINOR__ == 1
14 #define IMMER_BROKEN_STANDARD_LAYOUT_DETECTION 1
15 #define immer_offsetof(st, m) ((std::size_t) &(((st*)0)->m))
16 #else
17 #define IMMER_BROKEN_STANDARD_LAYOUT_DETECTION 0
18 #define immer_offsetof offsetof
19 #endif
20 
21 namespace immer {
22 namespace detail {
23 
24 //
25 // Metafunction that returns a standard layout struct that combines
26 // all the standard layout types in `Ts...`, while making sure that
27 // empty base optimizations are used.
28 //
29 // To query a part of the type do `get<my_part>(x)`;
30 //
31 // This is useful when putting together a type that merges various
32 // types coming from different policies. Some of them might be empty,
33 // so we shall enable empty base optimizations. But if we just
34 // inherit from all of them, we would break the "standard layout"
35 // rules, preventing us from using `offseof(...)`. So metafunction
36 // will generate the type by sometimes inheriting, sometimes adding as
37 // member.
38 //
39 // Note that the types are added to the combined type from right to
40 // left!
41 //
42 template <typename... Ts>
44 
45 template <typename... Ts>
46 using combine_standard_layout_t = typename combine_standard_layout<Ts...>::type;
47 
48 namespace csl {
49 
50 template <typename T>
51 struct type_t {};
52 
53 template <typename U, typename T>
54 U& get(T& x);
55 
56 template <typename U, typename T>
57 const U& get(const T& x);
58 
59 template <typename T, typename Next=void>
60 struct inherit
61 {
62  struct type : T, Next
63  {
64  using Next::get_;
65 
66  template <typename U>
67  friend decltype(auto) get(type& x) { return x.get_(type_t<U>{}); }
68  template <typename U>
69  friend decltype(auto) get(const type& x) { return x.get_(type_t<U>{}); }
70 
71  T& get_(type_t<T>) { return *this; }
72  const T& get_(type_t<T>) const { return *this; }
73  };
74 };
75 
76 template <typename T>
77 struct inherit<T, void>
78 {
79  struct type : T
80  {
81  template <typename U>
82  friend decltype(auto) get(type& x) { return x.get_(type_t<U>{}); }
83  template <typename U>
84  friend decltype(auto) get(const type& x) { return x.get_(type_t<U>{}); }
85 
86  T& get_(type_t<T>) { return *this; }
87  const T& get_(type_t<T>) const { return *this; }
88  };
89 };
90 
91 template <typename T, typename Next=void>
92 struct member
93 {
94  struct type : Next
95  {
96  T d;
97 
98  using Next::get_;
99 
100  template <typename U>
101  friend decltype(auto) get(type& x) { return x.get_(type_t<U>{}); }
102  template <typename U>
103  friend decltype(auto) get(const type& x) { return x.get_(type_t<U>{}); }
104 
105  T& get_(type_t<T>) { return d; }
106  const T& get_(type_t<T>) const { return d; }
107  };
108 };
109 
110 template <typename T>
111 struct member<T, void>
112 {
113  struct type
114  {
115  T d;
116 
117  template <typename U>
118  friend decltype(auto) get(type& x) { return x.get_(type_t<U>{}); }
119  template <typename U>
120  friend decltype(auto) get(const type& x) { return x.get_(type_t<U>{}); }
121 
122  T& get_(type_t<T>) { return d; }
123  const T& get_(type_t<T>) const { return d; }
124  };
125 };
126 
127 template <typename T, typename Next>
129 {
130  struct type
131  {
132  Next n;
133  T d;
134 
135  template <typename U>
136  friend decltype(auto) get(type& x) { return x.get_(type_t<U>{}); }
137  template <typename U>
138  friend decltype(auto) get(const type& x) { return x.get_(type_t<U>{}); }
139 
140  T& get_(type_t<T>) { return d; }
141  const T& get_(type_t<T>) const { return d; }
142 
143  template <typename U>
144  auto get_(type_t<U> t) -> decltype(auto) { return n.get_(t); }
145  template <typename U>
146  auto get_(type_t<U> t) const -> decltype(auto) { return n.get_(t); }
147  };
148 };
149 
150 template <typename... Ts>
152 
153 template <typename T>
155 {
156  static_assert(std::is_standard_layout<T>::value, "");
157 
158  using type = typename std::conditional_t<
159  std::is_empty<T>::value,
162 };
163 
164 template <typename T, typename... Ts>
166 {
167  static_assert(std::is_standard_layout<T>::value, "");
168 
169  using this_t = T;
170  using next_t = typename combine_standard_layout_aux<Ts...>::type;
171 
172  static constexpr auto empty_this = std::is_empty<this_t>::value;
173  static constexpr auto empty_next = std::is_empty<next_t>::value;
174 
175  using type = typename std::conditional_t<
176  empty_this, inherit<this_t, next_t>,
177  std::conditional_t<
178  empty_next, member<this_t, next_t>,
180 };
181 
182 } // namespace csl
183 
184 using csl::get;
185 
186 template <typename... Ts>
188 {
190 #if !IMMER_BROKEN_STANDARD_LAYOUT_DETECTION
191  static_assert(std::is_standard_layout<type>::value, "");
192 #endif
193 };
194 
195 } // namespace detail
196 } // namespace immer
auto get_(type_t< U > t) const -> decltype(auto)
auto get_(type_t< U > t) -> decltype(auto)
typename std::conditional_t< std::is_empty< T >::value, csl::inherit< T >, csl::member< T > >::type type
typename combine_standard_layout< Ts... >::type combine_standard_layout_t
typename csl::combine_standard_layout_aux< Ts... >::type type
decltype(auto) friend get(type &x)
typename std::conditional_t< empty_this, inherit< this_t, next_t >, std::conditional_t< empty_next, member< this_t, next_t >, member_two< this_t, next_t > >>::type type
decltype(auto) friend get(type &x)
typename combine_standard_layout_aux< Ts... >::type next_t
Released under the MIT license