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
51namespace boost {
52namespace unit_test {
53
54// ************************************************************************** //
55// ************** is_forward_iterable ************** //
56// ************************************************************************** //
57
58#if defined(BOOST_TEST_FWD_ITERABLE_CXX03) && !defined(BOOST_TEST_DOXYGEN_DOC__)
59template<typename T>
60struct is_forward_iterable : public mpl::false_ {};
61
62template<typename T>
63struct is_forward_iterable<T const> : public is_forward_iterable<T> {};
64
65template<typename T>
66struct is_forward_iterable<T&> : public is_forward_iterable<T> {};
67
68template<typename T, typename A>
69struct is_forward_iterable< std::vector<T, A> > : public mpl::true_ {};
70
71template<typename T, typename A>
72struct is_forward_iterable< std::list<T, A> > : public mpl::true_ {};
73
74template<typename K, typename V, typename C, typename A>
75struct is_forward_iterable< std::map<K, V, C, A> > : public mpl::true_ {};
76
77template<typename K, typename C, typename A>
78struct is_forward_iterable< std::set<K, C, A> > : public mpl::true_ {};
79
80#else
81
82namespace ut_detail {
83
84template<typename T>
85struct 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.
91template <class T>
92struct has_member_size {
93private:
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
98public:
99 static bool const value = !std::is_same< decltype(test<T>( nullptr )), nil_t>::value;
100};
101
102//____________________________________________________________________________//
103
104template <class T>
105struct has_member_begin {
106private:
107 struct nil_t {};
108 template<typename U> static auto test( U* ) -> decltype(boost::declval<U>().begin());
109 template<typename> static nil_t test( ... );
110public:
111 static bool const value = !std::is_same< decltype(test<T>( nullptr )), nil_t>::value;
112};
113
114//____________________________________________________________________________//
115
116template <class T>
117struct has_member_end {
118private:
119 struct nil_t {};
120 template<typename U> static auto test( U* ) -> decltype(boost::declval<U>().end());
121 template<typename> static nil_t test( ... );
122public:
123 static bool const value = !std::is_same< decltype(test<T>( nullptr )), nil_t>::value;
124};
125
126//____________________________________________________________________________//
127
128template <class T, class enabled = void>
129struct is_forward_iterable_impl : std::false_type {
130};
131
132//____________________________________________________________________________//
133
134template <class T>
135struct 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. */
153template<typename T>
154struct 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
167