1 /*=============================================================================
2     Copyright (c) 2001-2011 Joel de Guzman
3     Copyright (c) 2006 Dan Marsden
4 
5     Distributed under the Boost Software License, Version 1.0. (See accompanying
6     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 ==============================================================================*/
8 #if !defined(FUSION_STRICTEST_TRAVERSAL_20060123_2101)
9 #define FUSION_STRICTEST_TRAVERSAL_20060123_2101
10 
11 #include <boost/fusion/support/config.hpp>
12 #include <boost/config.hpp>
13 #include <boost/mpl/or.hpp>
14 #include <boost/mpl/if.hpp>
15 #include <boost/fusion/support/category_of.hpp>
16 #include <boost/fusion/mpl.hpp>
17 #include <boost/fusion/algorithm/iteration/fold.hpp>
18 #include <boost/type_traits/remove_reference.hpp>
19 #include <boost/type_traits/is_convertible.hpp>
20 
21 namespace boost { namespace fusion
22 {
23     struct forward_traversal_tag;
24     struct bidirectional_traversal_tag;
25     struct random_access_traversal_tag;
26 
27     namespace detail
28     {
29         template<typename Tag1, typename Tag2,
30             bool Tag1Stricter = boost::is_convertible<Tag2,Tag1>::value>
31         struct stricter_traversal
32         {
33             typedef Tag1 type;
34         };
35 
36         template<typename Tag1, typename Tag2>
37         struct stricter_traversal<Tag1,Tag2,false>
38         {
39             typedef Tag2 type;
40         };
41 
42         struct strictest_traversal_impl
43         {
44             template<typename Sig>
45             struct result;
46 
47             template<typename StrictestSoFar, typename Next>
48             struct result<strictest_traversal_impl(StrictestSoFar, Next)>
49             {
50                 typedef typename remove_reference<Next>::type next_value;
51                 typedef typename remove_reference<StrictestSoFar>::type strictest_so_far;
52 
53                 typedef strictest_so_far tag1;
54                 typedef typename traits::category_of<next_value>::type tag2;
55 
56                 typedef typename stricter_traversal<tag1,tag2>::type type;
57             };
58 
59             // never called, but needed for decltype-based result_of (C++0x)
60 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
61             template<typename StrictestSoFar, typename Next>
62             BOOST_FUSION_GPU_ENABLED
63             typename result<strictest_traversal_impl(StrictestSoFar, Next)>::type
64             operator()(StrictestSoFar&&, Next&&) const;
65 #endif
66         };
67 
68         template<typename Sequence>
69         struct strictest_traversal
70             : result_of::fold<
71             Sequence, fusion::random_access_traversal_tag,
72             strictest_traversal_impl>
73         {};
74 
75     }
76 }}
77 
78 #endif
79