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)
6 // See http://www.boost.org/libs/test for the library home page.
9 //! Defines the is_forward_iterable collection type trait
10 // ***************************************************************************
12 #ifndef BOOST_TEST_UTILS_IS_FORWARD_ITERABLE_HPP
13 #define BOOST_TEST_UTILS_IS_FORWARD_ITERABLE_HPP
15 #if defined(BOOST_NO_CXX11_DECLTYPE) || \
16 defined(BOOST_NO_CXX11_NULLPTR) || \
17 defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES)
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
25 #if defined(BOOST_TEST_FWD_ITERABLE_CXX03)
27 #include <boost/mpl/bool.hpp>
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>
46 #include <type_traits>
49 //____________________________________________________________________________//
54 // ************************************************************************** //
55 // ************** is_forward_iterable ************** //
56 // ************************************************************************** //
58 #if defined(BOOST_TEST_FWD_ITERABLE_CXX03) && !defined(BOOST_TEST_DOXYGEN_DOC__)
60 struct is_forward_iterable : public mpl::false_ {};
63 struct is_forward_iterable<T const> : public is_forward_iterable<T> {};
66 struct is_forward_iterable<T&> : public is_forward_iterable<T> {};
68 template<typename T, typename A>
69 struct is_forward_iterable< std::vector<T, A> > : public mpl::true_ {};
71 template<typename T, typename A>
72 struct is_forward_iterable< std::list<T, A> > : public mpl::true_ {};
74 template<typename K, typename V, typename C, typename A>
75 struct is_forward_iterable< std::map<K, V, C, A> > : public mpl::true_ {};
77 template<typename K, typename C, typename A>
78 struct is_forward_iterable< std::set<K, C, A> > : public mpl::true_ {};
85 struct is_present : public mpl::true_ {};
87 //____________________________________________________________________________//
89 // some compiler do not implement properly decltype non expression involving members (eg. VS2013)
90 // a workaround is to use -> decltype syntax.
92 struct has_member_size {
95 template<typename U> static auto test( U* ) -> decltype(boost::declval<U>().size());
96 template<typename> static nil_t test( ... );
99 static bool const value = !std::is_same< decltype(test<T>( nullptr )), nil_t>::value;
102 //____________________________________________________________________________//
105 struct has_member_begin {
108 template<typename U> static auto test( U* ) -> decltype(boost::declval<U>().begin());
109 template<typename> static nil_t test( ... );
111 static bool const value = !std::is_same< decltype(test<T>( nullptr )), nil_t>::value;
114 //____________________________________________________________________________//
117 struct has_member_end {
120 template<typename U> static auto test( U* ) -> decltype(boost::declval<U>().end());
121 template<typename> static nil_t test( ... );
123 static bool const value = !std::is_same< decltype(test<T>( nullptr )), nil_t>::value;
126 //____________________________________________________________________________//
128 template <class T, class enabled = void>
129 struct is_forward_iterable_impl : std::false_type {
132 //____________________________________________________________________________//
135 struct is_forward_iterable_impl<
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
148 //____________________________________________________________________________//
150 } // namespace ut_detail
152 /*! Indicates that a specific type implements the forward iterable concept. */
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 };
161 #endif /* defined(BOOST_TEST_FWD_ITERABLE_CXX03) */
163 } // namespace unit_test
166 #endif // BOOST_TEST_UTILS_IS_FORWARD_ITERABLE_HPP