Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:52:42

0001 //  (C) Copyright Gennadiy Rozental 2001.
0002 //  Distributed under the Boost Software License, Version 1.0.
0003 //  (See accompanying file LICENSE_1_0.txt or copy at
0004 //  http://www.boost.org/LICENSE_1_0.txt)
0005 
0006 //  See http://www.boost.org/libs/test for the library home page.
0007 //
0008 //! @file
0009 //! Defines the is_forward_iterable collection type trait
0010 // ***************************************************************************
0011 
0012 #ifndef BOOST_TEST_UTILS_IS_FORWARD_ITERABLE_HPP
0013 #define BOOST_TEST_UTILS_IS_FORWARD_ITERABLE_HPP
0014 
0015 #if defined(BOOST_NO_CXX11_DECLTYPE) || \
0016     defined(BOOST_NO_CXX11_NULLPTR) || \
0017     defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES)
0018 
0019   // this feature works with VC2012 upd 5 while BOOST_NO_CXX11_TRAILING_RESULT_TYPES is defined
0020   #if !defined(BOOST_MSVC) || BOOST_MSVC_FULL_VER < 170061232 /* VC2012 upd 5 */
0021     #define BOOST_TEST_FWD_ITERABLE_CXX03
0022   #endif
0023 #endif
0024 
0025 #if defined(BOOST_TEST_FWD_ITERABLE_CXX03)
0026 // Boost
0027 #include <boost/mpl/bool.hpp>
0028 
0029 // STL
0030 #include <list>
0031 #include <vector>
0032 #include <map>
0033 #include <set>
0034 
0035 #else
0036 
0037 // Boost
0038 #include <boost/static_assert.hpp>
0039 #include <boost/utility/declval.hpp>
0040 #include <boost/type_traits/is_same.hpp>
0041 #include <boost/type_traits/remove_reference.hpp>
0042 #include <boost/type_traits/remove_cv.hpp>
0043 #include <boost/test/utils/is_cstring.hpp>
0044 
0045 // STL
0046 #include <utility>
0047 #include <type_traits>
0048 
0049 #endif
0050 //____________________________________________________________________________//
0051 
0052 namespace boost {
0053 namespace unit_test {
0054 
0055 template<typename T>
0056 struct is_forward_iterable;
0057 
0058 // ************************************************************************** //
0059 // **************             is_forward_iterable              ************** //
0060 // ************************************************************************** //
0061 
0062 #if defined(BOOST_TEST_FWD_ITERABLE_CXX03) && !defined(BOOST_TEST_DOXYGEN_DOC__)
0063 template<typename T>
0064 struct is_forward_iterable : public mpl::false_ {};
0065 
0066 template<typename T>
0067 struct is_forward_iterable<T const> : public is_forward_iterable<T> {};
0068 
0069 template<typename T>
0070 struct is_forward_iterable<T&> : public is_forward_iterable<T> {};
0071 
0072 template<typename T, std::size_t N>
0073 struct is_forward_iterable< T [N] > : public mpl::true_ {};
0074 
0075 template<typename T, typename A>
0076 struct is_forward_iterable< std::vector<T, A> > : public mpl::true_ {};
0077 
0078 template<typename T, typename A>
0079 struct is_forward_iterable< std::list<T, A> > : public mpl::true_ {};
0080 
0081 template<typename K, typename V, typename C, typename A>
0082 struct is_forward_iterable< std::map<K, V, C, A> > : public mpl::true_ {};
0083 
0084 template<typename K, typename C, typename A>
0085 struct is_forward_iterable< std::set<K, C, A> > : public mpl::true_ {};
0086 
0087 // string is also forward iterable, even if sometimes we want to treat the
0088 // assertions differently.
0089 template<>
0090 struct is_forward_iterable< std::string > : public mpl::true_ {};
0091 
0092 #else
0093 
0094 namespace ut_detail {
0095 
0096 // SFINAE helper
0097 template<typename T>
0098 struct is_present : public mpl::true_ {};
0099 
0100 //____________________________________________________________________________//
0101 
0102 // some compiler do not implement properly decltype non expression involving members (eg. VS2013)
0103 // a workaround is to use -> decltype syntax.
0104 template <class T>
0105 struct has_member_size {
0106 private:
0107     struct nil_t {};
0108     template<typename U> static auto  test( U* ) -> decltype(boost::declval<U>().size());
0109     template<typename>   static nil_t test( ... );
0110 
0111 public:
0112     static bool const value = !std::is_same< decltype(test<T>( nullptr )), nil_t>::value;
0113 };
0114 
0115 //____________________________________________________________________________//
0116 
0117 template <class T>
0118 struct has_member_begin {
0119 private:
0120     struct nil_t {};
0121     template<typename U>  static auto  test( U* ) -> decltype(std::begin(boost::declval<U&>())); // does not work with boost::begin
0122     template<typename>    static nil_t test( ... );
0123 public:
0124     static bool const value = !std::is_same< decltype(test<T>( nullptr )), nil_t>::value;
0125 };
0126 
0127 //____________________________________________________________________________//
0128 
0129 template <class T>
0130 struct has_member_end {
0131 private:
0132     struct nil_t {};
0133     template<typename U>  static auto  test( U* ) -> decltype(std::end(boost::declval<U&>())); // does not work with boost::end
0134     template<typename>    static nil_t test( ... );
0135 public:
0136     static bool const value = !std::is_same< decltype(test<T>( nullptr )), nil_t>::value;
0137 };
0138 
0139 //____________________________________________________________________________//
0140 
0141 template <class T, class enabled = void>
0142 struct is_forward_iterable_impl : std::false_type {
0143 };
0144 
0145 template <class T>
0146 struct is_forward_iterable_impl<
0147     T,
0148     typename std::enable_if<
0149       has_member_begin<T>::value &&
0150       has_member_end<T>::value
0151     >::type
0152 > : std::true_type
0153 {};
0154 
0155 //____________________________________________________________________________//
0156 
0157 template <class T, class enabled = void>
0158 struct is_container_forward_iterable_impl : std::false_type {
0159 };
0160 
0161 template <class T>
0162 struct is_container_forward_iterable_impl<
0163     T,
0164     typename std::enable_if<
0165       is_present<typename T::const_iterator>::value &&
0166       is_present<typename T::value_type>::value &&
0167       has_member_size<T>::value &&
0168       is_forward_iterable_impl<T>::value
0169     >::type
0170 > : is_forward_iterable_impl<T>
0171 {};
0172 
0173 //____________________________________________________________________________//
0174 
0175 } // namespace ut_detail
0176 
0177 /*! Indicates that a specific type implements the forward iterable concept. */
0178 template<typename T>
0179 struct is_forward_iterable {
0180     typedef typename std::remove_reference<T>::type T_ref;
0181     typedef ut_detail::is_forward_iterable_impl<T_ref> is_fwd_it_t;
0182     typedef mpl::bool_<is_fwd_it_t::value> type;
0183     enum { value = is_fwd_it_t::value };
0184 };
0185 
0186 /*! Indicates that a specific type implements the forward iterable concept. */
0187 template<typename T>
0188 struct is_container_forward_iterable {
0189     typedef typename std::remove_reference<T>::type T_ref;
0190     typedef ut_detail::is_container_forward_iterable_impl<T_ref> is_fwd_it_t;
0191     typedef mpl::bool_<is_fwd_it_t::value> type;
0192     enum { value = is_fwd_it_t::value };
0193 };
0194 
0195 #endif /* defined(BOOST_TEST_FWD_ITERABLE_CXX03) */
0196 
0197 
0198 //! Helper structure for accessing the content of a container or an array
0199 template <typename T, bool is_forward_iterable = is_forward_iterable<T>::value >
0200 struct bt_iterator_traits;
0201 
0202 template <typename T>
0203 struct bt_iterator_traits< T, true >{
0204     BOOST_STATIC_ASSERT((is_forward_iterable<T>::value));
0205 
0206 #if defined(BOOST_TEST_FWD_ITERABLE_CXX03) || \
0207     (defined(BOOST_MSVC) && (BOOST_MSVC_FULL_VER <= 170061232))
0208     typedef typename T::const_iterator const_iterator;
0209     typedef typename std::iterator_traits<const_iterator>::value_type value_type;
0210 #else
0211     typedef decltype(boost::declval<
0212         typename boost::add_const<
0213           typename boost::remove_reference<T>::type
0214         >::type>().begin()) const_iterator;
0215 
0216     typedef typename std::iterator_traits<const_iterator>::value_type value_type;
0217 #endif /* BOOST_TEST_FWD_ITERABLE_CXX03 */
0218 
0219     static const_iterator begin(T const& container) {
0220         return container.begin();
0221     }
0222     static const_iterator end(T const& container) {
0223         return container.end();
0224     }
0225 
0226 #if defined(BOOST_TEST_FWD_ITERABLE_CXX03) || \
0227     (defined(BOOST_MSVC) && (BOOST_MSVC_FULL_VER <= 170061232))
0228     static std::size_t
0229     size(T const& container) {
0230         return container.size();
0231     }
0232 #else
0233     static std::size_t
0234     size(T const& container) {
0235         return size(container,
0236                     std::integral_constant<bool, ut_detail::has_member_size<T>::value>());
0237     }
0238 private:
0239     static std::size_t
0240     size(T const& container, std::true_type)  { return container.size(); }
0241 
0242     static std::size_t
0243     size(T const& container, std::false_type) { return std::distance(begin(container), end(container)); }
0244 #endif /* BOOST_TEST_FWD_ITERABLE_CXX03 */
0245 };
0246 
0247 template <typename T, std::size_t N>
0248 struct bt_iterator_traits< T [N], true > {
0249     typedef typename boost::add_const<T>::type T_const;
0250     typedef typename boost::add_pointer<T_const>::type const_iterator;
0251     typedef T value_type;
0252 
0253     static const_iterator begin(T_const (&array)[N]) {
0254         return &array[0];
0255     }
0256     static const_iterator end(T_const (&array)[N]) {
0257         return &array[N];
0258     }
0259     static std::size_t size(T_const (&)[N]) {
0260         return N;
0261     }
0262 };
0263 
0264 } // namespace unit_test
0265 } // namespace boost
0266 
0267 #endif // BOOST_TEST_UTILS_IS_FORWARD_ITERABLE_HPP