1// Boost.TypeErasure library
2//
3// Copyright 2011 Steven Watanabe
4//
5// Distributed under the Boost Software License Version 1.0. (See
6// accompanying file LICENSE_1_0.txt or copy at
7// http://www.boost.org/LICENSE_1_0.txt)
8//
9// $Id$
10
11#ifndef BOOST_TYPE_ERASURE_DETAIL_NORMALIZE_HPP_INCLUDED
12#define BOOST_TYPE_ERASURE_DETAIL_NORMALIZE_HPP_INCLUDED
13
14#include <boost/mpl/assert.hpp>
15#include <boost/mpl/eval_if.hpp>
16#include <boost/mpl/identity.hpp>
17#include <boost/mpl/is_sequence.hpp>
18#include <boost/mpl/set.hpp>
19#include <boost/mpl/map.hpp>
20#include <boost/mpl/has_key.hpp>
21#include <boost/mpl/insert.hpp>
22#include <boost/mpl/vector.hpp>
23#include <boost/mpl/back_inserter.hpp>
24#include <boost/mpl/inserter.hpp>
25#include <boost/mpl/fold.hpp>
26#include <boost/mpl/transform.hpp>
27#include <boost/mpl/copy.hpp>
28#include <boost/mpl/at.hpp>
29#include <boost/type_traits/is_same.hpp>
30#include <boost/type_erasure/detail/get_placeholders.hpp>
31#include <boost/type_erasure/detail/rebind_placeholders.hpp>
32#include <boost/type_erasure/detail/normalize_deduced.hpp>
33#include <boost/type_erasure/detail/meta.hpp>
34#include <boost/type_erasure/relaxed.hpp>
35#include <boost/type_erasure/builtin.hpp>
36
37namespace boost {
38namespace type_erasure {
39
40template<class F>
41struct deduced;
42
43template<class T, class U>
44struct same_type;
45
46namespace detail {
47struct substitution_map_tag {};
48
49// a wrapper around an mpl::map that
50// defaults to the identity map.
51template<class M>
52struct substitution_map
53{
54 typedef substitution_map_tag tag;
55 typedef M map_type;
56};
57
58}
59}
60
61namespace mpl {
62
63template<>
64struct at_impl< ::boost::type_erasure::detail::substitution_map_tag>
65{
66 template<class Seq, class Key>
67 struct apply
68 {
69 typedef typename ::boost::mpl::eval_if<
70 ::boost::mpl::has_key<typename Seq::map_type, Key>,
71 ::boost::mpl::at<typename Seq::map_type, Key>,
72 ::boost::mpl::identity<Key>
73 >::type type;
74 };
75};
76
77template<>
78struct has_key_impl< ::boost::type_erasure::detail::substitution_map_tag>
79{
80 template<class Seq, class Key>
81 struct apply : boost::mpl::true_
82 {};
83};
84
85}
86
87namespace type_erasure {
88namespace detail {
89
90// Given the arguments to same_type, determines
91// which should be the key and which should be
92// the value in the substitution map.
93template<class T, class U>
94struct select_pair
95{
96 BOOST_MPL_ASSERT((::boost::is_same<T, U>));
97 typedef void type;
98};
99
100template<class T, class U>
101struct select_pair<T, ::boost::type_erasure::deduced<U> >
102{
103 typedef ::boost::mpl::pair< ::boost::type_erasure::deduced<U>, T> type;
104};
105
106template<class T, class U>
107struct select_pair< ::boost::type_erasure::deduced<T>, U>
108{
109 typedef ::boost::mpl::pair< ::boost::type_erasure::deduced<T>, U> type;
110};
111
112template<class T, class U>
113struct select_pair<
114 ::boost::type_erasure::deduced<T>,
115 ::boost::type_erasure::deduced<U>
116>
117{
118 typedef ::boost::mpl::pair<
119 ::boost::type_erasure::deduced<T>,
120 ::boost::type_erasure::deduced<U>
121 > type;
122};
123
124#ifndef BOOST_TYPE_ERASURE_USE_MP11
125
126// given a partial substitution map from same_type,
127// resolves a placeholder as far as possible.
128template<class M, class T>
129struct resolve_same_type
130{
131 typedef typename ::boost::mpl::eval_if< ::boost::mpl::has_key<M, T>,
132 ::boost::type_erasure::detail::resolve_same_type<
133 M,
134 typename ::boost::mpl::at<M, T>::type
135 >,
136 ::boost::mpl::identity<T>
137 >::type type;
138};
139
140// M is a map of placeholder substitutions
141template<class M, class T>
142struct normalize_placeholder
143{
144 typedef typename ::boost::mpl::eval_if< ::boost::mpl::has_key<M, T>,
145 ::boost::type_erasure::detail::normalize_placeholder<
146 M,
147 typename ::boost::mpl::at<M, T>::type
148 >,
149 ::boost::mpl::identity<T>
150 >::type type;
151};
152
153template<class M, class T>
154struct normalize_placeholder<M, ::boost::type_erasure::deduced<T> >
155{
156 typedef typename ::boost::mpl::eval_if< ::boost::mpl::has_key<M, T>,
157 ::boost::type_erasure::detail::normalize_placeholder<
158 M,
159 typename ::boost::mpl::at<M, T>::type
160 >,
161 ::boost::type_erasure::detail::normalize_deduced<
162 M,
163 T
164 >
165 >::type type;
166};
167
168// Takes a mpl::map of placeholder substitutions and
169// fully resolves it. i.e. a -> b, b -> c, becomes
170// a -> c, b -> c. Also resolves deduced placeholders
171// whose arguments are all resolved.
172template<class M>
173struct create_placeholder_map
174{
175 typedef typename ::boost::mpl::fold<
176 M,
177 ::boost::mpl::map0<>,
178 ::boost::mpl::insert<
179 ::boost::mpl::_1,
180 ::boost::mpl::pair<
181 ::boost::mpl::first< ::boost::mpl::_2>,
182 ::boost::type_erasure::detail::normalize_placeholder<M, ::boost::mpl::second< ::boost::mpl::_2> >
183 >
184 >
185 >::type type;
186};
187
188template<class Bindings, class P, class Out, class Sub>
189struct convert_deduced
190{
191 typedef typename ::boost::type_erasure::detail::rebind_placeholders_in_argument<
192 typename P::first,
193 Bindings
194 >::type result1;
195 typedef typename ::boost::mpl::at<Sub, result1>::type result;
196 typedef typename ::boost::mpl::eval_if<
197 ::boost::mpl::has_key<Out, typename P::second>,
198 ::boost::mpl::identity<Out>,
199 ::boost::mpl::insert<Out, ::boost::mpl::pair<typename P::second, result> >
200 >::type type;
201 BOOST_MPL_ASSERT((boost::is_same<typename ::boost::mpl::at<type, typename P::second>::type, result>));
202};
203
204template<class Bindings, class M, class Sub>
205struct convert_deductions
206{
207 typedef typename ::boost::mpl::fold<
208 M,
209 Bindings,
210 ::boost::type_erasure::detail::convert_deduced<
211 Bindings, ::boost::mpl::_2, ::boost::mpl::_1, Sub
212 >
213 >::type type;
214};
215
216template<class Bindings, class P, class Out>
217struct add_deduced
218{
219 typedef typename ::boost::type_erasure::detail::rebind_placeholders_in_argument<
220 typename P::first,
221 Bindings
222 >::type result;
223 typedef typename ::boost::mpl::eval_if<
224 ::boost::mpl::has_key<Out, typename P::second>,
225 ::boost::mpl::identity<Out>,
226 ::boost::mpl::insert<Out, ::boost::mpl::pair<typename P::second, result> >
227 >::type type;
228 BOOST_MPL_ASSERT((boost::is_same<typename ::boost::mpl::at<type, typename P::second>::type, result>));
229};
230
231template<class Bindings, class M>
232struct add_deductions
233{
234 typedef typename ::boost::mpl::fold<
235 M,
236 Bindings,
237 ::boost::type_erasure::detail::add_deduced<
238 Bindings, ::boost::mpl::_2, ::boost::mpl::_1
239 >
240 >::type type;
241};
242
243// Fold Op for normalize_concept_impl
244template<class Out, class T>
245struct insert_concept
246{
247 typedef ::boost::mpl::pair<
248 typename ::boost::mpl::insert<typename Out::first, T>::type,
249 typename Out::second
250 > type;
251};
252
253template<class Out, class T, class U>
254struct insert_concept<Out, ::boost::type_erasure::same_type<T, U> >
255{
256 typedef typename ::boost::type_erasure::detail::resolve_same_type<
257 typename Out::second,
258 T
259 >::type t1;
260 typedef typename ::boost::type_erasure::detail::resolve_same_type<
261 typename Out::second,
262 U
263 >::type t2;
264 typedef ::boost::mpl::pair<
265 typename Out::first,
266 typename ::boost::mpl::eval_if<
267 ::boost::is_same<t1, t2>,
268 ::boost::mpl::identity<typename Out::second>,
269 ::boost::mpl::insert<
270 typename Out::second,
271 typename ::boost::type_erasure::detail::select_pair<
272 t1,
273 t2
274 >::type
275 >
276 >::type
277 > type;
278};
279
280// flattens a concept returning an mpl::pair
281// - first is an MPL sequence containing the leaf concepts
282// - second is an MPL map of the placeholder substitutions
283// used to resolve same_type.
284template<class Concept, class Out = ::boost::mpl::pair< ::boost::mpl::set0<>, ::boost::mpl::map0<> > >
285struct normalize_concept_impl
286{
287 typedef typename ::boost::mpl::eval_if< ::boost::mpl::is_sequence<Concept>,
288 ::boost::mpl::fold<Concept, Out, normalize_concept_impl< ::boost::mpl::_2, ::boost::mpl::_1> >,
289 ::boost::type_erasure::detail::insert_concept<Out, Concept>
290 >::type type;
291};
292
293struct append_typeinfo
294{
295 template<class Set, class T>
296 struct apply
297 {
298 typedef typename ::boost::mpl::insert<
299 Set,
300 ::boost::type_erasure::typeid_<T>
301 >::type type;
302 };
303};
304
305// Seq should be a flattened MPL sequence of leaf concepts.
306// adds typeid_<P> for every placeholder used.
307template<class Seq>
308struct add_typeinfo
309{
310 typedef typename ::boost::mpl::fold<
311 Seq,
312 ::boost::mpl::set0<>,
313 ::boost::type_erasure::detail::get_placeholders<
314 ::boost::mpl::_2,
315 ::boost::mpl::_1
316 >
317 >::type placeholders;
318 typedef typename ::boost::mpl::fold<
319 placeholders,
320 Seq,
321 ::boost::type_erasure::detail::append_typeinfo
322 >::type type;
323};
324
325template<class Concept>
326struct get_placeholder_normalization_map
327{
328 typedef typename ::boost::type_erasure::detail::create_placeholder_map<
329 typename normalize_concept_impl<Concept>::type::second
330 >::type type;
331};
332
333// Flattens a Concept to an mpl::vector of primitive
334// concepts. Resolves same_type and deduced placeholders.
335template<class Concept>
336struct normalize_concept
337{
338 typedef typename normalize_concept_impl<Concept>::type impl;
339 typedef typename ::boost::type_erasure::detail::create_placeholder_map<
340 typename impl::second
341 >::type substitutions;
342 typedef typename ::boost::mpl::fold<
343 typename impl::first,
344 ::boost::mpl::set0<>,
345 ::boost::mpl::insert<
346 ::boost::mpl::_1,
347 ::boost::type_erasure::detail::rebind_placeholders<
348 ::boost::mpl::_2,
349 ::boost::type_erasure::detail::substitution_map<substitutions>
350 >
351 >
352 >::type basic;
353 typedef typename ::boost::mpl::eval_if<
354 ::boost::type_erasure::is_relaxed<Concept>,
355 ::boost::type_erasure::detail::add_typeinfo<basic>,
356 ::boost::mpl::identity<basic>
357 >::type concept_set;
358 typedef typename ::boost::mpl::copy<
359 concept_set,
360 ::boost::mpl::back_inserter< ::boost::mpl::vector0<> >
361 >::type type;
362};
363
364// Returns an MPL sequence containing all the concepts
365// in Concept. If Concept is considered as a DAG,
366// the result will be sorted topologically.
367template<
368 class Concept,
369 class Map = typename ::boost::type_erasure::detail::create_placeholder_map<
370 typename ::boost::type_erasure::detail::normalize_concept_impl<
371 Concept
372 >::type::second
373 >::type,
374 class Out = ::boost::mpl::set0<>
375>
376struct collect_concepts
377{
378 typedef typename ::boost::type_erasure::detail::rebind_placeholders<
379 Concept,
380 ::boost::type_erasure::detail::substitution_map<Map>
381 >::type transformed;
382 typedef typename ::boost::mpl::eval_if< ::boost::mpl::is_sequence<Concept>,
383 ::boost::mpl::fold<Concept, Out, collect_concepts< ::boost::mpl::_2, Map, ::boost::mpl::_1> >,
384 ::boost::mpl::identity<Out>
385 >::type type1;
386 typedef typename ::boost::mpl::eval_if<
387 ::boost::is_same<transformed, void>,
388 ::boost::mpl::identity<type1>,
389 ::boost::mpl::insert<
390 type1,
391 transformed
392 >
393 >::type type;
394};
395
396#else
397
398template<bool>
399struct resolve_same_type_impl;
400
401template<class M, class T>
402using resolve_same_type_t =
403 typename ::boost::type_erasure::detail::resolve_same_type_impl<
404 (::boost::mp11::mp_map_contains<M, T>::value)
405 >::template apply<M, T>;
406
407template<>
408struct resolve_same_type_impl<true>
409{
410 template<class M, class T>
411 using apply = ::boost::type_erasure::detail::resolve_same_type_t<
412 M,
413 ::boost::mp11::mp_second< ::boost::mp11::mp_map_find<M, T> >
414 >;
415};
416
417template<>
418struct resolve_same_type_impl<false>
419{
420 template<class M, class T>
421 using apply = T;
422};
423
424// given a partial substitution map from same_type,
425// resolves a placeholder as far as possible.
426template<class M, class T>
427using resolve_same_type = ::boost::mpl::identity< ::boost::type_erasure::detail::resolve_same_type_t<M, T> >;
428
429
430// M is a map of placeholder substitutions
431
432template<bool>
433struct normalize_placeholder_impl;
434
435template<class M, class T>
436using normalize_placeholder_t =
437 typename ::boost::type_erasure::detail::normalize_placeholder_impl<
438 ::boost::mp11::mp_map_contains<M, T>::value
439 >::template apply<M, T>;
440
441template<>
442struct normalize_placeholder_impl<true>
443{
444 template<class M, class T>
445 using apply = ::boost::type_erasure::detail::normalize_placeholder_t<
446 M,
447 typename ::boost::mp11::mp_second< ::boost::mp11::mp_map_find<M, T> >
448 >;
449};
450
451template<class T>
452struct normalize_deduced_impl
453{
454 template<class Map>
455 using apply = T;
456};
457
458template<template<class...> class F, class... T>
459struct normalize_deduced_impl< ::boost::type_erasure::deduced<F<T...> > >
460{
461 template<class Map>
462 using apply = typename ::boost::type_erasure::deduced<F<normalize_placeholder_t<Map, T>...> >::type;
463};
464
465template<>
466struct normalize_placeholder_impl<false>
467{
468 template<class M, class T>
469 using apply = typename ::boost::type_erasure::detail::normalize_deduced_impl<T>::template apply<M>;
470};
471
472template<class Map, class T>
473using normalize_placeholder = ::boost::mpl::identity< ::boost::type_erasure::detail::normalize_placeholder_t<Map, T> >;
474
475// Takes a mpl::map of placeholder substitutions and
476// fully resolves it. i.e. a -> b, b -> c, becomes
477// a -> c, b -> c. Also resolves deduced placeholders
478// whose arguments are all resolved.
479template<class M>
480struct create_placeholder_map
481{
482 template<class P>
483 using transform_one = ::boost::mpl::pair<
484 typename ::boost::mpl::first<P>::type,
485 ::boost::type_erasure::detail::normalize_placeholder_t<
486 M,
487 typename ::boost::mpl::second<P>::type
488 >
489 >;
490 typedef ::boost::mp11::mp_transform<
491 transform_one,
492 M
493 > type;
494};
495
496template<class M>
497using create_placeholder_map_t = typename ::boost::type_erasure::detail::create_placeholder_map<M>::type;
498
499template<class Bindings, class P, class Out, class Sub>
500struct convert_deduced
501{
502 typedef ::boost::type_erasure::detail::rebind_placeholders_in_argument_t<
503 typename P::first,
504 Bindings
505 > result1;
506 typedef ::boost::mp11::mp_second< ::boost::mp11::mp_map_find<Sub, result1> > result;
507 typedef ::boost::mp11::mp_map_insert<Out, ::boost::mpl::pair<typename P::second, result> > type;
508 BOOST_MPL_ASSERT((boost::is_same< ::boost::mp11::mp_second< ::boost::mp11::mp_map_find<type, typename P::second> >, result>));
509};
510
511template<class Bindings, class Sub>
512struct convert_deduced_f
513{
514 template<class Out, class P>
515 using apply = typename ::boost::type_erasure::detail::convert_deduced<Bindings, P, Out, Sub>::type;
516};
517
518template<class Bindings, class M, class Sub>
519using convert_deductions_t =
520 ::boost::mp11::mp_fold<
521 M,
522 ::boost::type_erasure::detail::make_mp_list<Bindings>,
523 ::boost::type_erasure::detail::convert_deduced_f<Bindings, Sub>::template apply
524 >;
525
526template<class Bindings, class M, class Sub>
527using convert_deductions = ::boost::mpl::identity< ::boost::type_erasure::detail::convert_deductions_t<Bindings, M, Sub> >;
528
529template<class Bindings, class P, class Out>
530struct add_deduced
531{
532 typedef typename ::boost::type_erasure::detail::rebind_placeholders_in_argument<
533 typename P::first,
534 Bindings
535 >::type result;
536 typedef ::boost::mp11::mp_map_insert<Out, ::boost::mpl::pair<typename P::second, result> > type;
537 BOOST_MPL_ASSERT((boost::is_same< ::boost::mp11::mp_second< ::boost::mp11::mp_map_find<type, typename P::second> >, result>));
538};
539
540template<class Bindings>
541struct add_deduced_f
542{
543 template<class Out, class P>
544 using apply = typename ::boost::type_erasure::detail::add_deduced<Bindings, P, Out>::type;
545};
546
547template<class Bindings, class M>
548using add_deductions_t =
549 ::boost::mp11::mp_fold<
550 M,
551 ::boost::type_erasure::detail::make_mp_list<Bindings>,
552 ::boost::type_erasure::detail::add_deduced_f<
553 ::boost::type_erasure::detail::make_mp_list<Bindings>
554 >::template apply
555 >;
556
557template<class Bindings, class M>
558using add_deductions = ::boost::mpl::identity< ::boost::type_erasure::detail::add_deductions_t<Bindings, M> >;
559
560// Fold Op for normalize_concept_impl
561template<class T>
562struct insert_concept_impl
563{
564 template<class Out>
565 using apply =
566 ::boost::mpl::pair<
567 ::boost::mp11::mp_set_push_back<typename Out::first, T>,
568 typename Out::second
569 >;
570};
571
572template<class Map, class T>
573using mpl_insert = typename ::boost::mpl::insert<Map, T>::type;
574
575template<class T1, class T2, class Out>
576using insert_concept_same_type =
577 ::boost::mpl::pair<
578 typename Out::first,
579 typename ::boost::type_erasure::detail::eval_if<
580 ::boost::is_same<T1, T2>::value,
581 ::boost::type_erasure::detail::first,
582 ::boost::mp11::mp_map_insert, // FIXME: is this supposed to be a replace?
583 typename Out::second,
584 typename ::boost::type_erasure::detail::select_pair<
585 T1,
586 T2
587 >::type
588 >
589 >;
590
591template<class T, class U>
592struct insert_concept_impl< ::boost::type_erasure::same_type<T, U> >
593{
594 template<class Out>
595 using apply = ::boost::type_erasure::detail::insert_concept_same_type<
596 ::boost::type_erasure::detail::resolve_same_type_t<
597 typename Out::second,
598 T
599 >,
600 ::boost::type_erasure::detail::resolve_same_type_t<
601 typename Out::second,
602 U
603 >,
604 Out
605 >;
606};
607
608template<bool>
609struct normalize_concept_impl_test;
610
611template<class Out, class Concept>
612using normalize_concept_impl_f =
613 typename ::boost::type_erasure::detail::normalize_concept_impl_test<
614 ::boost::mpl::is_sequence<Concept>::value
615 >::template apply<Out, Concept>;
616
617template<>
618struct normalize_concept_impl_test<true>
619{
620 template<class Out, class Concept>
621 using apply =
622 ::boost::mp11::mp_fold<
623 ::boost::type_erasure::detail::make_mp_list<Concept>,
624 Out,
625 ::boost::type_erasure::detail::normalize_concept_impl_f
626 >;
627};
628
629template<>
630struct normalize_concept_impl_test<false>
631{
632 template<class Out, class Concept>
633 using apply = typename ::boost::type_erasure::detail::insert_concept_impl<Concept>::template apply<Out>;
634};
635
636template<class Concept>
637using normalize_concept_impl_t =
638 ::boost::type_erasure::detail::normalize_concept_impl_f<
639 ::boost::mpl::pair< ::boost::mp11::mp_list<>, ::boost::mp11::mp_list<> >,
640 Concept
641 >;
642
643template<class Concept>
644using normalize_concept_impl = ::boost::mpl::identity< ::boost::type_erasure::detail::normalize_concept_impl_t<Concept> >;
645
646template<class S, class T>
647using get_all_placeholders_impl = typename ::boost::type_erasure::detail::get_placeholders<T, S>::type;
648
649template<class Seq>
650using get_all_placeholders =
651 ::boost::mp11::mp_fold<
652 Seq,
653 ::boost::mp11::mp_list<>,
654 ::boost::type_erasure::detail::get_all_placeholders_impl
655 >;
656
657template<class T>
658using make_identity_pair = ::boost::mpl::pair<T, T>;
659
660template<class Concept>
661using make_identity_placeholder_map =
662 ::boost::mp11::mp_transform<
663 ::boost::type_erasure::detail::make_identity_pair,
664 ::boost::type_erasure::detail::get_all_placeholders<
665 typename normalize_concept_impl_t<Concept>::first
666 >
667 >;
668
669template<class S, class T>
670using append_type_info = ::boost::mp11::mp_set_push_back<
671 S,
672 ::boost::type_erasure::typeid_<T>
673>;
674
675template<class Seq>
676using add_typeinfo_t =
677 ::boost::mp11::mp_fold<
678 get_all_placeholders<Seq>,
679 Seq,
680 ::boost::type_erasure::detail::append_type_info
681 >;
682
683// Seq should be a flattened mp_list sequence of leaf concepts.
684// adds typeid_<P> for every placeholder used.
685template<class Seq>
686using add_typeinfo = ::boost::mpl::identity<add_typeinfo_t<Seq> >;
687
688template<class Substitutions>
689struct normalize_concept_substitute_f
690{
691 template<class Set, class Concept>
692 using apply = ::boost::mp11::mp_set_push_back<Set,
693 typename ::boost::type_erasure::detail::rebind_placeholders<
694 Concept,
695 Substitutions
696 >::type
697 >;
698};
699
700template<class Concept, class Pair>
701using normalize_concept_adjustments =
702 ::boost::type_erasure::detail::eval_if<
703 ::boost::type_erasure::is_relaxed<Concept>::value,
704 ::boost::type_erasure::detail::add_typeinfo_t,
705 ::boost::type_erasure::detail::first,
706 ::boost::mp11::mp_fold<
707 typename Pair::first,
708 ::boost::mp11::mp_list<>,
709 ::boost::type_erasure::detail::normalize_concept_substitute_f<
710 ::boost::type_erasure::detail::create_placeholder_map_t<
711 typename Pair::second
712 >
713 >::template apply
714 >
715 >;
716
717template<class Concept>
718using get_placeholder_normalization_map_t =
719 ::boost::type_erasure::detail::create_placeholder_map_t<
720 typename normalize_concept_impl_t<Concept>::second
721 >;
722
723template<class Concept>
724using get_placeholder_normalization_map =
725 ::boost::type_erasure::detail::create_placeholder_map<
726 typename normalize_concept_impl_t<Concept>::second
727 >;
728
729// Flattens a Concept to an mpl::vector of primitive
730// concepts. Resolves same_type and deduced placeholders.
731template<class Concept>
732using normalize_concept_t =
733 ::boost::type_erasure::detail::normalize_concept_adjustments<
734 Concept,
735 boost::type_erasure::detail::normalize_concept_impl_t<Concept>
736 >;
737
738template<class Concept>
739using normalize_concept = ::boost::mpl::identity< ::boost::type_erasure::detail::normalize_concept_t<Concept> >;
740
741template<class Map>
742struct collect_concepts_f;
743
744template<class Out, class Concept, class Map>
745using collect_concepts_recursive = ::boost::mp11::mp_fold<
746 ::boost::type_erasure::detail::make_mp_list<Concept>,
747 Out,
748 ::boost::type_erasure::detail::collect_concepts_f<Map>::template apply
749>;
750
751template<class Concept, class Map, class Out, class Transformed>
752using collect_concepts_impl =
753 ::boost::type_erasure::detail::eval_if< ::boost::is_same<Transformed, void>::value,
754 ::boost::type_erasure::detail::first,
755 ::boost::mp11::mp_set_push_front,
756 ::boost::type_erasure::detail::eval_if< ::boost::mpl::is_sequence<Concept>::value,
757 ::boost::type_erasure::detail::collect_concepts_recursive,
758 ::boost::type_erasure::detail::first,
759 Out,
760 Concept,
761 Map
762 >,
763 Transformed
764 >;
765
766template<class Concept,
767 class Map = ::boost::type_erasure::detail::create_placeholder_map_t<
768 typename ::boost::type_erasure::detail::normalize_concept_impl_t<
769 Concept
770 >::second
771 >,
772 class Out = ::boost::mp11::mp_list<>
773>
774using collect_concepts_t =
775 collect_concepts_impl<Concept, Map, Out,
776 typename ::boost::type_erasure::detail::rebind_placeholders<
777 Concept,
778 Map
779 >::type
780 >;
781
782template<class Map>
783struct collect_concepts_f
784{
785 template<class Out, class Concept>
786 using apply = ::boost::type_erasure::detail::collect_concepts_t<Concept, Map, Out>;
787};
788
789// Returns an MPL sequence containing all the concepts
790// in Concept. If Concept is considered as a DAG,
791// the result will be sorted topologically.
792template<class Concept>
793using collect_concepts = ::boost::mpl::identity<
794 ::boost::type_erasure::detail::collect_concepts_t<Concept> >;
795
796#endif
797
798}
799}
800}
801
802#endif
803

source code of boost/libs/type_erasure/include/boost/type_erasure/detail/normalize.hpp