1 /* { dg-do compile } */
2 /* { dg-options "-O2 -std=gnu++14 -fdump-tree-sra" } */
6 #define EGGS_CXX11_CONSTEXPR constexpr
7 #define EGGS_CXX11_STATIC_CONSTEXPR static constexpr
8 #define EGGS_CXX14_CONSTEXPR constexpr
9 #define EGGS_CXX11_NOEXCEPT noexcept
11 namespace eggs { namespace variants { namespace detail
15 EGGS_CXX11_CONSTEXPR bool operator==(empty) const { return true; }
16 EGGS_CXX11_CONSTEXPR bool operator<(empty) const { return false; }
25 template <std::size_t I>
28 EGGS_CXX11_STATIC_CONSTEXPR std::size_t value = I;
31 template <typename ...Ts>
35 EGGS_CXX11_STATIC_CONSTEXPR std::size_t size = sizeof...(Ts);
38 template <typename T, T ...Vs>
42 EGGS_CXX11_STATIC_CONSTEXPR std::size_t size = sizeof...(Vs);
45 ///////////////////////////////////////////////////////////////////////////
46 template <typename Is, bool Odd>
47 struct _make_index_pack_twice;
49 template <std::size_t ...Is>
50 struct _make_index_pack_twice<
51 pack_c<std::size_t, Is...>
53 > : pack_c<std::size_t, Is..., (sizeof...(Is) + Is)...>
56 template <std::size_t ...Is>
57 struct _make_index_pack_twice<
58 pack_c<std::size_t, Is...>
60 > : pack_c<std::size_t, Is..., (sizeof...(Is) + Is)..., sizeof...(Is) * 2>
63 template <std::size_t N>
64 struct _make_index_pack
65 : _make_index_pack_twice<
66 typename _make_index_pack<N / 2>::type
72 struct _make_index_pack<1>
73 : pack_c<std::size_t, 0>
77 struct _make_index_pack<0>
81 template <std::size_t N>
82 using make_index_pack = typename _make_index_pack<N>::type;
84 template <typename Ts>
87 template <typename ...Ts>
88 struct _index_pack<pack<Ts...>>
89 : _make_index_pack<sizeof...(Ts)>
92 template <typename Ts>
93 using index_pack = typename _index_pack<Ts>::type;
95 ///////////////////////////////////////////////////////////////////////////
96 template <typename Vs>
100 struct all_of<pack_c<bool, Vs...>>
101 : std::integral_constant<
105 , pack_c<bool, (Vs || true)...> // true...
110 template <typename ...Ts>
111 struct all_of<pack<Ts...>>
112 : all_of<pack_c<bool, (Ts::value)...>>
115 template <typename ...Vs>
118 template <bool ...Vs>
119 struct any_of<pack_c<bool, Vs...>>
120 : std::integral_constant<
122 , !all_of<pack_c<bool, !Vs...>>::value
126 template <typename ...Ts>
127 struct any_of<pack<Ts...>>
128 : any_of<pack_c<bool, (Ts::value)...>>
131 ///////////////////////////////////////////////////////////////////////////
132 template <std::size_t I, typename T>
135 template <typename Ts, typename Is = index_pack<Ts>>
138 template <typename ...Ts, std::size_t ...Is>
139 struct _indexer<pack<Ts...>, pack_c<std::size_t, Is...>>
140 : _indexed<Is, Ts>...
143 empty _at_index(...);
145 template <std::size_t I, typename T>
146 identity<T> _at_index(_indexed<I, T> const&);
148 template <std::size_t I, typename Ts>
150 : decltype(_at_index<I>(_indexer<Ts>{}))
153 empty _index_of(...);
155 template <typename T, std::size_t I>
156 index<I> _index_of(_indexed<I, T> const&);
158 template <typename T, typename Ts>
160 : decltype(_index_of<T>(_indexer<Ts>{}))
164 namespace eggs { namespace variants { namespace detail
166 template <typename Ts, bool IsTriviallyDestructible>
169 ///////////////////////////////////////////////////////////////////////////
170 template <bool IsTriviallyDestructible>
171 struct _union<pack<>, IsTriviallyDestructible>
174 template <typename T, typename ...Ts>
175 struct _union<pack<T, Ts...>, true>
177 EGGS_CXX11_STATIC_CONSTEXPR std::size_t size = 1 + sizeof...(Ts);
179 template <typename ...Args>
180 EGGS_CXX11_CONSTEXPR _union(index<0>, Args&&... args)
181 : _head(std::forward<Args>(args)...)
184 template <std::size_t I, typename ...Args>
185 EGGS_CXX11_CONSTEXPR _union(index<I>, Args&&... args)
186 : _tail(index<I - 1>{}, std::forward<Args>(args)...)
189 EGGS_CXX14_CONSTEXPR void* target() EGGS_CXX11_NOEXCEPT
194 EGGS_CXX11_CONSTEXPR void const* target() const EGGS_CXX11_NOEXCEPT
199 EGGS_CXX14_CONSTEXPR T& get(index<0>) EGGS_CXX11_NOEXCEPT
204 EGGS_CXX11_CONSTEXPR T const& get(index<0>) const EGGS_CXX11_NOEXCEPT
211 , typename U = typename at_index<I, pack<T, Ts...>>::type
213 EGGS_CXX14_CONSTEXPR U& get(index<I>) EGGS_CXX11_NOEXCEPT
215 return this->_tail.get(index<I - 1>{});
220 , typename U = typename at_index<I, pack<T, Ts...>>::type
222 EGGS_CXX11_CONSTEXPR U const& get(index<I>) const EGGS_CXX11_NOEXCEPT
224 return this->_tail.get(index<I - 1>{});
232 _union<pack<Ts...>, true> _tail;
236 ///////////////////////////////////////////////////////////////////////////
237 template <typename Ts, bool TriviallyCopyable, bool TriviallyDestructible>
240 template <typename ...Ts>
241 struct _storage<pack<Ts...>, true, true>
244 , all_of<pack<std::is_trivially_destructible<Ts>...>>::value
247 using base_type = _union<
249 , all_of<pack<std::is_trivially_destructible<Ts>...>>::value
252 EGGS_CXX11_CONSTEXPR _storage() EGGS_CXX11_NOEXCEPT
253 : base_type{index<0>{}}
257 _storage(_storage const& rhs) = default;
258 _storage(_storage&& rhs) = default;
260 template <std::size_t I, typename ...Args>
261 EGGS_CXX11_CONSTEXPR _storage(index<I> which, Args&&... args)
262 : base_type{which, std::forward<Args>(args)...}
266 _storage& operator=(_storage const& rhs) = default;
267 _storage& operator=(_storage&& rhs) = default;
269 EGGS_CXX11_CONSTEXPR std::size_t which() const
274 using base_type::target;
275 using base_type::get;
281 template <typename ...Ts>
282 using storage = _storage<
284 , all_of<pack<std::is_trivially_copyable<Ts>...>>::value
285 , all_of<pack<std::is_trivially_destructible<Ts>...>>::value
289 namespace eggs { namespace variants
291 template <typename ...Ts>
296 ///////////////////////////////////////////////////////////////////////
297 namespace _best_match
299 template <typename Ts, std::size_t I = 0>
303 template <typename T, typename ...Ts, std::size_t I>
304 struct overloads<pack<T, Ts...>, I>
305 : overloads<pack<Ts...>, I + 1>
307 using fun_ptr = index<I>(*)(T);
311 template <typename F, typename T>
312 auto _invoke(F&&, T&&)
313 -> decltype(std::declval<F>()(std::declval<T>()));
317 _fallback _invoke(...);
320 typename T, typename U
321 , typename R = decltype(_best_match::_invoke(
322 std::declval<T>(), std::declval<U>()))
327 template <typename T, typename U>
328 struct result_of<T, U, _fallback>
332 template <typename U, typename ...Ts>
333 struct index_of_best_match
334 : _best_match::result_of<_best_match::overloads<Ts...>, U>
339 template <typename ...Ts>
344 EGGS_CXX11_CONSTEXPR variant() EGGS_CXX11_NOEXCEPT = delete;
346 variant(variant const& rhs) = default;
348 variant(variant&& rhs) = default;
352 , typename Enable = typename std::enable_if<!std::is_same<
353 typename std::decay<U>::type, variant
355 , std::size_t I = detail::index_of_best_match<
356 U&&, detail::pack<Ts...>>::value
357 , typename T = typename detail::at_index<
358 I, detail::pack<Ts...>>::type
360 EGGS_CXX11_CONSTEXPR variant(U&& v)
362 std::is_nothrow_constructible<T, U&&>::value)
363 : _storage{detail::index<I + 1>{}, std::forward<U>(v)}
366 ~variant() = default;
367 variant& operator=(variant const& rhs) = delete;
370 detail::storage<Ts...> _storage;
374 template <class T, class Base>
375 struct ref_proxy : Base
385 : Base(std::move(ptr))
393 explicit inplace_ref(T inner)
401 template <class ...Variants>
404 variant_ref() = delete;
406 explicit variant_ref(eggs::variants::variant<Variants...> t)
411 template <class Source>
412 variant_ref(ref_proxy<Source, variant_ref> ptr)
413 : inner_storage_(ptr.inner_storage_)
417 eggs::variants::variant<Variants...> inner_storage_;
422 void *a, *b, *c, *d, *e;
429 using option_ref = variant_ref<option_1, option_2>;
434 qual_option(ref_proxy<void, option_ref > type, int quals)
440 explicit qual_option(ref_proxy<void, option_ref > type)
441 : qual_option(type, 0)
445 ref_proxy<void, option_ref > type_;
449 inline ref_proxy<option_2, option_ref > make_object_1()
451 return ref_proxy<option_2, option_ref >(option_2());
454 inline ref_proxy<option_2, option_ref > make_object_2()
456 return make_object_1();
459 inline inplace_ref<qual_option> make_object_3(ref_proxy<option_2, option_ref>&& a0)
461 return inplace_ref<qual_option>(qual_option(a0));
464 inline ref_proxy<qual_option, inplace_ref<qual_option> > make_object_4(ref_proxy<option_2, option_ref>&& a0)
466 return make_object_3(std::move(a0));
470 ref_proxy<qual_option, inplace_ref<qual_option> > f() __attribute__((noinline));
472 ref_proxy<qual_option, inplace_ref<qual_option> > f()
474 return make_object_4(make_object_2());
477 int main(int argc, char* argv[])
483 /* { dg-final { scan-tree-dump "Removing load:.*ptr;" "sra" } } */