]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // (C) Copyright Gennadiy Rozental 2001. |
2 | // Distributed under the Boost Software License, Version 1.0. | |
3 | // (See accompanying file LICENSE_1_0.txt or copy at | |
4 | // http://www.boost.org/LICENSE_1_0.txt) | |
5 | ||
6 | // See http://www.boost.org/libs/test for the library home page. | |
7 | // | |
8 | //! @file | |
9 | //! Defines the is_forward_iterable collection type trait | |
10 | // *************************************************************************** | |
11 | ||
12 | #ifndef BOOST_TEST_UTILS_IS_FORWARD_ITERABLE_HPP | |
13 | #define BOOST_TEST_UTILS_IS_FORWARD_ITERABLE_HPP | |
14 | ||
15 | #if defined(BOOST_NO_CXX11_DECLTYPE) || \ | |
16 | defined(BOOST_NO_CXX11_NULLPTR) || \ | |
17 | defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) | |
18 | ||
19 | // some issues with boost.config | |
20 | #if !defined(BOOST_MSVC) || BOOST_MSVC_FULL_VER < 170061030 /* VC2012 upd 5 */ | |
21 | #define BOOST_TEST_FWD_ITERABLE_CXX03 | |
22 | #endif | |
23 | #endif | |
24 | ||
25 | #if defined(BOOST_TEST_FWD_ITERABLE_CXX03) | |
26 | // Boost | |
27 | #include <boost/mpl/bool.hpp> | |
28 | ||
29 | // STL | |
30 | #include <list> | |
31 | #include <vector> | |
32 | #include <map> | |
33 | #include <set> | |
34 | ||
35 | #else | |
36 | ||
37 | // Boost | |
38 | #include <boost/utility/declval.hpp> | |
39 | #include <boost/type_traits/is_same.hpp> | |
40 | #include <boost/type_traits/remove_reference.hpp> | |
41 | #include <boost/type_traits/remove_cv.hpp> | |
42 | #include <boost/test/utils/is_cstring.hpp> | |
43 | ||
44 | // STL | |
45 | #include <utility> | |
46 | #include <type_traits> | |
47 | ||
48 | #endif | |
49 | //____________________________________________________________________________// | |
50 | ||
51 | namespace boost { | |
52 | namespace unit_test { | |
53 | ||
54 | // ************************************************************************** // | |
55 | // ************** is_forward_iterable ************** // | |
56 | // ************************************************************************** // | |
57 | ||
58 | #if defined(BOOST_TEST_FWD_ITERABLE_CXX03) && !defined(BOOST_TEST_DOXYGEN_DOC__) | |
59 | template<typename T> | |
60 | struct is_forward_iterable : public mpl::false_ {}; | |
61 | ||
62 | template<typename T> | |
63 | struct is_forward_iterable<T const> : public is_forward_iterable<T> {}; | |
64 | ||
65 | template<typename T> | |
66 | struct is_forward_iterable<T&> : public is_forward_iterable<T> {}; | |
67 | ||
68 | template<typename T, typename A> | |
69 | struct is_forward_iterable< std::vector<T, A> > : public mpl::true_ {}; | |
70 | ||
71 | template<typename T, typename A> | |
72 | struct is_forward_iterable< std::list<T, A> > : public mpl::true_ {}; | |
73 | ||
74 | template<typename K, typename V, typename C, typename A> | |
75 | struct is_forward_iterable< std::map<K, V, C, A> > : public mpl::true_ {}; | |
76 | ||
77 | template<typename K, typename C, typename A> | |
78 | struct is_forward_iterable< std::set<K, C, A> > : public mpl::true_ {}; | |
79 | ||
80 | #else | |
81 | ||
82 | namespace ut_detail { | |
83 | ||
84 | template<typename T> | |
85 | struct is_present : public mpl::true_ {}; | |
86 | ||
87 | //____________________________________________________________________________// | |
88 | ||
89 | // some compiler do not implement properly decltype non expression involving members (eg. VS2013) | |
90 | // a workaround is to use -> decltype syntax. | |
91 | template <class T> | |
92 | struct has_member_size { | |
93 | private: | |
94 | struct nil_t {}; | |
95 | template<typename U> static auto test( U* ) -> decltype(boost::declval<U>().size()); | |
96 | template<typename> static nil_t test( ... ); | |
97 | ||
98 | public: | |
99 | static bool const value = !std::is_same< decltype(test<T>( nullptr )), nil_t>::value; | |
100 | }; | |
101 | ||
102 | //____________________________________________________________________________// | |
103 | ||
104 | template <class T> | |
105 | struct has_member_begin { | |
106 | private: | |
107 | struct nil_t {}; | |
108 | template<typename U> static auto test( U* ) -> decltype(boost::declval<U>().begin()); | |
109 | template<typename> static nil_t test( ... ); | |
110 | public: | |
111 | static bool const value = !std::is_same< decltype(test<T>( nullptr )), nil_t>::value; | |
112 | }; | |
113 | ||
114 | //____________________________________________________________________________// | |
115 | ||
116 | template <class T> | |
117 | struct has_member_end { | |
118 | private: | |
119 | struct nil_t {}; | |
120 | template<typename U> static auto test( U* ) -> decltype(boost::declval<U>().end()); | |
121 | template<typename> static nil_t test( ... ); | |
122 | public: | |
123 | static bool const value = !std::is_same< decltype(test<T>( nullptr )), nil_t>::value; | |
124 | }; | |
125 | ||
126 | //____________________________________________________________________________// | |
127 | ||
128 | template <class T, class enabled = void> | |
129 | struct is_forward_iterable_impl : std::false_type { | |
130 | }; | |
131 | ||
132 | //____________________________________________________________________________// | |
133 | ||
134 | template <class T> | |
135 | struct is_forward_iterable_impl< | |
136 | T, | |
137 | typename std::enable_if< | |
138 | is_present<typename T::const_iterator>::value && | |
139 | is_present<typename T::value_type>::value && | |
140 | has_member_size<T>::value && | |
141 | has_member_begin<T>::value && | |
142 | has_member_end<T>::value && | |
143 | !is_cstring<T>::value | |
144 | >::type | |
145 | > : std::true_type | |
146 | {}; | |
147 | ||
148 | //____________________________________________________________________________// | |
149 | ||
150 | } // namespace ut_detail | |
151 | ||
152 | /*! Indicates that a specific type implements the forward iterable concept. */ | |
153 | template<typename T> | |
154 | struct is_forward_iterable { | |
155 | typedef typename std::remove_reference<T>::type T_ref; | |
156 | typedef ut_detail::is_forward_iterable_impl<T_ref> is_fwd_it_t; | |
157 | typedef mpl::bool_<is_fwd_it_t::value> type; | |
158 | enum { value = is_fwd_it_t::value }; | |
159 | }; | |
160 | ||
161 | #endif /* defined(BOOST_TEST_FWD_ITERABLE_CXX03) */ | |
162 | ||
163 | } // namespace unit_test | |
164 | } // namespace boost | |
165 | ||
166 | #endif // BOOST_TEST_UTILS_IS_FORWARD_ITERABLE_HPP |