// (C) Copyright Gennadiy Rozental 2001. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // See http://www.boost.org/libs/test for the library home page. // //! @file //! Defines the is_forward_iterable collection type trait // *************************************************************************** #ifndef BOOST_TEST_UTILS_IS_FORWARD_ITERABLE_HPP #define BOOST_TEST_UTILS_IS_FORWARD_ITERABLE_HPP #if defined(BOOST_NO_CXX11_DECLTYPE) || \ defined(BOOST_NO_CXX11_NULLPTR) || \ defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) // some issues with boost.config #if !defined(BOOST_MSVC) || BOOST_MSVC_FULL_VER < 170061030 /* VC2012 upd 5 */ #define BOOST_TEST_FWD_ITERABLE_CXX03 #endif #endif #if defined(BOOST_TEST_FWD_ITERABLE_CXX03) // Boost #include // STL #include #include #include #include #else // Boost #include #include #include #include #include // STL #include #include #endif //____________________________________________________________________________// namespace boost { namespace unit_test { // ************************************************************************** // // ************** is_forward_iterable ************** // // ************************************************************************** // #if defined(BOOST_TEST_FWD_ITERABLE_CXX03) && !defined(BOOST_TEST_DOXYGEN_DOC__) template struct is_forward_iterable : public mpl::false_ {}; template struct is_forward_iterable : public is_forward_iterable {}; template struct is_forward_iterable : public is_forward_iterable {}; template struct is_forward_iterable< std::vector > : public mpl::true_ {}; template struct is_forward_iterable< std::list > : public mpl::true_ {}; template struct is_forward_iterable< std::map > : public mpl::true_ {}; template struct is_forward_iterable< std::set > : public mpl::true_ {}; // string is also forward iterable, even if sometimes we want to treat the // assertions differently. template<> struct is_forward_iterable< std::string > : public mpl::true_ {}; #else namespace ut_detail { template struct is_present : public mpl::true_ {}; //____________________________________________________________________________// // some compiler do not implement properly decltype non expression involving members (eg. VS2013) // a workaround is to use -> decltype syntax. template struct has_member_size { private: struct nil_t {}; template static auto test( U* ) -> decltype(boost::declval().size()); template static nil_t test( ... ); public: static bool const value = !std::is_same< decltype(test( nullptr )), nil_t>::value; }; //____________________________________________________________________________// template struct has_member_begin { private: struct nil_t {}; template static auto test( U* ) -> decltype(boost::declval().begin()); template static nil_t test( ... ); public: static bool const value = !std::is_same< decltype(test( nullptr )), nil_t>::value; }; //____________________________________________________________________________// template struct has_member_end { private: struct nil_t {}; template static auto test( U* ) -> decltype(boost::declval().end()); template static nil_t test( ... ); public: static bool const value = !std::is_same< decltype(test( nullptr )), nil_t>::value; }; //____________________________________________________________________________// template struct is_forward_iterable_impl : std::false_type { }; //____________________________________________________________________________// template struct is_forward_iterable_impl< T, typename std::enable_if< is_present::value && is_present::value && has_member_size::value && has_member_begin::value && has_member_end::value && !is_cstring::value >::type > : std::true_type {}; //____________________________________________________________________________// } // namespace ut_detail /*! Indicates that a specific type implements the forward iterable concept. */ template struct is_forward_iterable { typedef typename std::remove_reference::type T_ref; typedef ut_detail::is_forward_iterable_impl is_fwd_it_t; typedef mpl::bool_ type; enum { value = is_fwd_it_t::value }; }; #endif /* defined(BOOST_TEST_FWD_ITERABLE_CXX03) */ } // namespace unit_test } // namespace boost #endif // BOOST_TEST_UTILS_IS_FORWARD_ITERABLE_HPP