diff options
Diffstat (limited to 'boost/convert/detail')
-rw-r--r-- | boost/convert/detail/boost_parameter_ext.hpp | 62 | ||||
-rw-r--r-- | boost/convert/detail/char.hpp | 23 | ||||
-rw-r--r-- | boost/convert/detail/forward.hpp | 39 | ||||
-rw-r--r-- | boost/convert/detail/has_member.hpp | 61 | ||||
-rw-r--r-- | boost/convert/detail/is_callable.hpp | 100 | ||||
-rw-r--r-- | boost/convert/detail/is_converter.hpp | 47 | ||||
-rw-r--r-- | boost/convert/detail/is_fun.hpp | 61 | ||||
-rw-r--r-- | boost/convert/detail/is_string.hpp | 34 | ||||
-rw-r--r-- | boost/convert/detail/range.hpp | 112 |
9 files changed, 539 insertions, 0 deletions
diff --git a/boost/convert/detail/boost_parameter_ext.hpp b/boost/convert/detail/boost_parameter_ext.hpp new file mode 100644 index 0000000000..a384018cfb --- /dev/null +++ b/boost/convert/detail/boost_parameter_ext.hpp @@ -0,0 +1,62 @@ +// Copyright (c) 2009-2014 Vladimir Batov. +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. + +#ifndef BOOST_PARAMETER_EXT_PRIVATE_HPP +#define BOOST_PARAMETER_EXT_PRIVATE_HPP + +#include <boost/parameter/keyword.hpp> + +// A Boost.Parameter extension by Andrey Semashev. +// This should really go to Boost.Parameter in the end. + +namespace boost { namespace parameter { + +// The metafunction, given the type of the arguments pack and the keyword tag, +// returns the corresponding parameter type +template< typename ArgsT, typename KeywordTagT > +struct parameter_type +{ + typedef void type; +}; + +template< typename ArgT, typename KeywordTagT > +struct parameter_type<aux::tagged_argument<KeywordTagT, ArgT>, KeywordTagT> +{ + typedef typename aux::tagged_argument< KeywordTagT, ArgT >::value_type type; +}; + +template< typename KeywordTagT1, typename ArgT, typename KeywordTagT2 > +struct parameter_type< aux::tagged_argument< KeywordTagT1, ArgT >, KeywordTagT2 > +{ + typedef void type; +}; + +template< typename ArgT, typename TailT, typename KeywordTagT > +struct parameter_type< + aux::arg_list< + aux::tagged_argument< KeywordTagT, ArgT >, + TailT + >, + KeywordTagT +> +{ + typedef typename aux::tagged_argument< KeywordTagT, ArgT >::value_type type; +}; + +template< typename KeywordTagT1, typename ArgT, typename TailT, typename KeywordTagT2 > +struct parameter_type< + aux::arg_list< + aux::tagged_argument< KeywordTagT1, ArgT >, + TailT + >, + KeywordTagT2 +> : + public parameter_type< TailT, KeywordTagT2 > +{ +}; + +}} // boost::parameter + +#endif // BOOST_PARAMETER_EXT_PRIVATE_HPP + diff --git a/boost/convert/detail/char.hpp b/boost/convert/detail/char.hpp new file mode 100644 index 0000000000..5b3cbda10e --- /dev/null +++ b/boost/convert/detail/char.hpp @@ -0,0 +1,23 @@ +// Copyright (c) 2009-2014 Vladimir Batov. +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. + +#ifndef BOOST_CONVERT_DETAIL_IS_CHAR_HPP +#define BOOST_CONVERT_DETAIL_IS_CHAR_HPP + +#include <boost/mpl/bool.hpp> +#include <boost/type_traits/remove_const.hpp> + +namespace boost { namespace cnv +{ + namespace detail + { + template<typename T> struct is_char : mpl::false_ {}; + template<> struct is_char<char> : mpl:: true_ {}; + template<> struct is_char<wchar_t> : mpl:: true_ {}; + } + template <typename T> struct is_char : detail::is_char<typename remove_const<T>::type> {}; +}} + +#endif // BOOST_CONVERT_DETAIL_IS_CHAR_HPP + diff --git a/boost/convert/detail/forward.hpp b/boost/convert/detail/forward.hpp new file mode 100644 index 0000000000..5548aec3fe --- /dev/null +++ b/boost/convert/detail/forward.hpp @@ -0,0 +1,39 @@ +// Copyright (c) 2009-2014 Vladimir Batov. +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. + +#ifndef BOOST_CONVERT_FORWARD_HPP +#define BOOST_CONVERT_FORWARD_HPP + +#if defined(_MSC_VER) +# pragma warning(disable: 4244) +# pragma warning(disable: 4224) +# pragma warning(disable: 4996) +# pragma warning(disable: 4180) // qualifier applied to function type has no meaning +# pragma warning(disable: 4100) // unreferenced formal parameter + +#if _MSC_VER < 1900 /* MSVC-14 defines real snprintf()... just about time! */ +# define snprintf _snprintf +#endif + +#endif + +#include <boost/config.hpp> +#include <boost/version.hpp> +#include <boost/optional.hpp> + +#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_NO_CXX11_RVALUE_REFERENCES) +#undef BOOST_CONVERT_CXX11 +#else +#define BOOST_CONVERT_CXX11 +#endif + +#if defined(BOOST_INTEL) && (BOOST_INTEL <= 1200) /* Intel 12.0 and lower have broken SFINAE */ +# define BOOST_CONVERT_INTEL_SFINAE_BROKEN +#endif + +#if defined(BOOST_MSVC) && (BOOST_MSVC < 1800) /* MSVC-11 and lower have broken SFINAE */ +# define BOOST_CONVERT_MSVC_SFINAE_BROKEN +#endif + +#endif // BOOST_CONVERT_FORWARD_HPP diff --git a/boost/convert/detail/has_member.hpp b/boost/convert/detail/has_member.hpp new file mode 100644 index 0000000000..fafc39f5c4 --- /dev/null +++ b/boost/convert/detail/has_member.hpp @@ -0,0 +1,61 @@ +// Copyright (c) 2009-2014 Vladimir Batov. +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. + +#ifndef BOOST_CONVERT_HAS_MEMBER_HPP +#define BOOST_CONVERT_HAS_MEMBER_HPP + +#include <boost/type_traits/remove_const.hpp> +#include <boost/type_traits/detail/yes_no_type.hpp> + +// This macro allows to check if a type has a member named "__member_name__"... +// ... regardless of the signature. If takes advantage of the following behavior related to +// function resolution. Say, both, foo and base, declare a method with the same name "func": +// +// struct foo { int func (int, int) { return 0; } }; +// struct base { void func () {} }; +// struct mixin : public foo, public base {}; +// +// Now, if we inherit from both -- foo and base -- classes, then the following calls will fail +// mixin_ptr(0)->func(); +// mixin_ptr(0)->func(5, 5); +// with the error message (gcc): request for member func is ambiguous +// regardless if we provide any arguments or not even though one might expect that +// arg-based signature resolution might kick in. The only way to deploy those methods is: +// +// mixin_ptr(0)->foo::func(); +// mixin_ptr(0)->base::func(5, 5); +// +// C2. The actual signature of __member_name__ is not taken into account. If +// __T__::__member_name__(any-signature) exists, then the introduced base::__member_name__ +// will cause mixin->__member_name__() call to fail to compile (due to ambiguity). +// C3. &U::__member_name__ (a.k.a. &mixin::__member_name__) +// has the type of func_type only if __T__::__member_name__ does not exist. +// If __T__::member_name does exist, then mixin::__member_name__ is ambiguous +// and "yes_type test (...)" kicks in instead. +// C4. Need to find some unique/ugly name so that it does not clash if this macro is +// used inside some other template class; + +#define BOOST_DECLARE_HAS_MEMBER(__trait_name__, __member_name__) \ + \ + template <typename __boost_has_member_T__> /*C4*/ \ + class __trait_name__ \ + { \ + typedef typename ::boost::remove_const<__boost_has_member_T__>::type check_type; \ + typedef ::boost::type_traits::yes_type yes_type; \ + typedef ::boost::type_traits:: no_type no_type; \ + \ + struct base { void __member_name__(/*C2*/) {}}; \ + struct mixin : public base, public check_type {}; \ + \ + template <void (base::*)()> struct aux {}; \ + \ + template <typename U> static no_type test(aux<&U::__member_name__>*); /*C3*/ \ + template <typename U> static yes_type test(...); \ + \ + public: \ + \ + BOOST_STATIC_CONSTANT(bool, value = (sizeof(yes_type) == sizeof(test<mixin>(0)))); \ + } + +#endif // BOOST_CONVERT_HAS_MEMBER_HPP diff --git a/boost/convert/detail/is_callable.hpp b/boost/convert/detail/is_callable.hpp new file mode 100644 index 0000000000..d516fdc05b --- /dev/null +++ b/boost/convert/detail/is_callable.hpp @@ -0,0 +1,100 @@ +// Copyright (c) 2009-2014 Vladimir Batov. +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. + +#ifndef BOOST_CONVERT_IS_CALLABLE_HPP +#define BOOST_CONVERT_IS_CALLABLE_HPP + +#include <boost/convert/detail/has_member.hpp> + +namespace boost { namespace cnv { namespace detail +{ + typedef ::boost::type_traits::yes_type yes_type; + typedef ::boost::type_traits:: no_type no_type; + + struct not_found {}; + struct void_return_substitute {}; + + // The overloaded comma operator only kicks in for U != void essentially short-circuiting + // itself ineffective. Otherwise, when U=void, the standard op,() kicks in and returns + // 'void_return_substitute'. + template<typename U> U const& operator, (U const&, void_return_substitute); + template<typename U> U& operator, (U&, void_return_substitute); + + template <typename src, typename dst> struct match_const { typedef dst type; }; + template <typename src, typename dst> struct match_const<src const, dst> { typedef dst const type; }; + + template<typename T, typename return_type> + struct redirect + { + static no_type test (...); + static yes_type test (return_type); + }; + + template<typename T> + struct redirect<T, void> + { + static yes_type test (...); + static no_type test (not_found); + }; +}}} + +// No-args case needs to be implemented differently and has not been implemented yet. +// template <typename R> +// struct check<true, R ()> + +// C1. Need to find some unique/ugly names so that they do not clash if this macro is +// used inside some other template class; +// C2. Body of the function is not actually used anywhere. +// However, Intel C++ compiler treats it as an error. So, we provide the body. + +#define BOOST_DECLARE_IS_CALLABLE(__trait_name__, __member_name__) \ + \ +template <typename __boost_is_callable_T__, typename __boost_is_callable_signature__> \ +class __trait_name__ \ +{ \ + typedef __boost_is_callable_T__ class_type; /*C1*/ \ + typedef __boost_is_callable_signature__ signature; /*C1*/ \ + typedef boost::cnv::detail::not_found not_found; \ + \ + BOOST_DECLARE_HAS_MEMBER(has_member, __member_name__); \ + \ + struct mixin : public class_type \ + { \ + using class_type::__member_name__; \ + not_found __member_name__(...) const { return not_found(); /*C2*/} \ + }; \ + \ + typedef typename boost::cnv::detail::match_const<class_type, mixin>::type* mixin_ptr; \ + \ + template <bool has, typename F> struct check { static bool const value = false; }; \ + \ + template <typename Arg1, typename R> \ + struct check<true, R (Arg1)> \ + { \ + typedef typename boost::decay<Arg1>::type* a1; \ + \ + static bool const value = sizeof(boost::type_traits::yes_type) \ + == sizeof(boost::cnv::detail::redirect<class_type, R>::test( \ + (mixin_ptr(0)->__member_name__(*a1(0)), \ + boost::cnv::detail::void_return_substitute()))); \ + }; \ + template <typename Arg1, typename Arg2, typename R> \ + struct check<true, R (Arg1, Arg2)> \ + { \ + typedef typename boost::decay<Arg1>::type* a1; \ + typedef typename boost::decay<Arg2>::type* a2; \ + \ + static bool const value = sizeof(boost::type_traits::yes_type) \ + == sizeof(boost::cnv::detail::redirect<class_type, R>::test( \ + (mixin_ptr(0)->__member_name__(*a1(0), *a2(0)), \ + boost::cnv::detail::void_return_substitute()))); \ + }; \ + \ + public: \ + \ + /* Check the existence of __member_name__ first, then the signature. */ \ + static bool const value = check<has_member<class_type>::value, signature>::value; \ +} + +#endif // BOOST_CONVERT_IS_CALLABLE_HPP diff --git a/boost/convert/detail/is_converter.hpp b/boost/convert/detail/is_converter.hpp new file mode 100644 index 0000000000..b35470cd19 --- /dev/null +++ b/boost/convert/detail/is_converter.hpp @@ -0,0 +1,47 @@ +// Copyright (c) 2009-2014 Vladimir Batov. +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. + +#ifndef BOOST_CONVERT_IS_CONVERTER_HPP +#define BOOST_CONVERT_IS_CONVERTER_HPP + +#include <boost/convert/detail/forward.hpp> +#include <boost/convert/detail/is_callable.hpp> +#include <boost/utility/enable_if.hpp> +#include <boost/type_traits.hpp> +#include <boost/ref.hpp> + +namespace boost { namespace cnv +{ + template<typename, typename, typename, typename =void> + struct is_cnv { BOOST_STATIC_CONSTANT(bool, value = false); }; + + template<typename Class, typename TypeIn, typename TypeOut> + struct is_cnv<Class, TypeIn, TypeOut, typename enable_if<is_class<Class>, void>::type> + { + typedef typename ::boost::unwrap_reference<Class>::type class_type; + typedef void signature_type(TypeIn const&, optional<TypeOut>&); + + BOOST_DECLARE_IS_CALLABLE(is_callable, operator()); + + BOOST_STATIC_CONSTANT(bool, value = (is_callable<class_type, signature_type>::value)); + }; + + template<typename Function, typename TypeIn, typename TypeOut> + struct is_cnv<Function, TypeIn, TypeOut, + typename enable_if_c<is_function<Function>::value && function_types::function_arity<Function>::value == 2, + void>::type> + { + typedef TypeIn in_type; + typedef optional<TypeOut>& out_type; + typedef typename function_traits<Function>::arg1_type func_in_type; + typedef typename function_traits<Function>::arg2_type func_out_type; + + BOOST_STATIC_CONSTANT(bool, in_good = (is_convertible<in_type, func_in_type>::value)); + BOOST_STATIC_CONSTANT(bool, out_good = (is_same<out_type, func_out_type>::value)); + BOOST_STATIC_CONSTANT(bool, value = (in_good && out_good)); + }; +}} + +#endif // BOOST_CONVERT_IS_CONVERTER_HPP + diff --git a/boost/convert/detail/is_fun.hpp b/boost/convert/detail/is_fun.hpp new file mode 100644 index 0000000000..5e1eae2ca6 --- /dev/null +++ b/boost/convert/detail/is_fun.hpp @@ -0,0 +1,61 @@ +// Copyright (c) 2009-2014 Vladimir Batov. +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. + +#ifndef BOOST_CONVERT_IS_FUNCTION_HPP +#define BOOST_CONVERT_IS_FUNCTION_HPP + +#include <boost/convert/detail/forward.hpp> +#include <boost/convert/detail/has_member.hpp> +#include <boost/utility/enable_if.hpp> +#include <boost/type_traits.hpp> +#include <boost/function_types/is_function_pointer.hpp> +#include <boost/function_types/function_arity.hpp> +#include <boost/function_types/result_type.hpp> + +namespace boost { namespace cnv +{ + typedef ::boost::type_traits::yes_type yes_type; + typedef ::boost::type_traits:: no_type no_type; + + template <bool has_operator, typename Functor, typename TypeOut> + struct check_functor { BOOST_STATIC_CONSTANT(bool, value = false); }; + + template<typename Func, typename TypeOut, class Enable =void> + struct is_fun { BOOST_STATIC_CONSTANT(bool, value = false); }; + + template <typename Functor, typename TypeOut> + struct check_functor<true, Functor, TypeOut> + { + static yes_type test (TypeOut const&); + static no_type test (...); + + static const bool value = sizeof(yes_type) == sizeof(test(((Functor*) 0)->operator()())); + }; + + template<typename Functor, typename TypeOut> + struct is_fun<Functor, TypeOut, + typename enable_if_c<is_class<Functor>::value && !is_convertible<Functor, TypeOut>::value, void>::type> + { + BOOST_DECLARE_HAS_MEMBER(has_funop, operator()); + + BOOST_STATIC_CONSTANT(bool, value = (check_functor<has_funop<Functor>::value, Functor, TypeOut>::value)); + }; + + template<typename Function, typename TypeOut> + struct is_fun<Function, TypeOut, + typename enable_if_c< + function_types::is_function_pointer<Function>::value && + function_types::function_arity<Function>::value == 0 && + !is_same<Function, TypeOut>::value, + void>::type> + { + typedef TypeOut out_type; + typedef typename function_types::result_type<Function>::type func_out_type; + + BOOST_STATIC_CONSTANT(bool, value = (is_convertible<func_out_type, out_type>::value)); + }; +}} + +#endif // BOOST_CONVERT_IS_FUNCTION_HPP + diff --git a/boost/convert/detail/is_string.hpp b/boost/convert/detail/is_string.hpp new file mode 100644 index 0000000000..ab682b0c72 --- /dev/null +++ b/boost/convert/detail/is_string.hpp @@ -0,0 +1,34 @@ +// Copyright (c) 2009-2014 Vladimir Batov. +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. + +#ifndef BOOST_CONVERT_DETAIL_IS_STRING_HPP +#define BOOST_CONVERT_DETAIL_IS_STRING_HPP + +#include <boost/convert/detail/range.hpp> + +namespace boost { namespace cnv +{ + namespace detail + { + template<typename T, bool is_range_class> struct is_string : mpl::false_ {}; + + template<typename T> struct is_string<T*, false> + { + static bool const value = cnv::is_char<T>::value; + }; + template <typename T, std::size_t N> struct is_string<T [N], false> + { + static bool const value = cnv::is_char<T>::value; + }; + template<typename T> struct is_string<T, /*is_range_class=*/true> + { + static bool const value = cnv::is_char<typename T::value_type>::value; + }; + } + template<typename T> struct is_string : detail::is_string< + typename remove_const<T>::type, + boost::is_class<T>::value && boost::cnv::is_range<T>::value> {}; +}} + +#endif // BOOST_CONVERT_DETAIL_IS_STRING_HPP diff --git a/boost/convert/detail/range.hpp b/boost/convert/detail/range.hpp new file mode 100644 index 0000000000..439fbf48d0 --- /dev/null +++ b/boost/convert/detail/range.hpp @@ -0,0 +1,112 @@ +// Copyright (c) 2009-2014 Vladimir Batov. +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. + +#ifndef BOOST_CONVERT_DETAIL_RANGE_HPP +#define BOOST_CONVERT_DETAIL_RANGE_HPP + +#include <boost/convert/detail/has_member.hpp> +#include <boost/convert/detail/char.hpp> +#include <boost/utility/enable_if.hpp> +#include <boost/range/iterator.hpp> + +namespace boost { namespace cnv +{ + namespace detail + { + template<typename T, bool is_class> struct is_range : mpl::false_ {}; + + template<typename T> struct is_range<T, /*is_class=*/true> + { + BOOST_DECLARE_HAS_MEMBER(has_begin, begin); + BOOST_DECLARE_HAS_MEMBER( has_end, end); + + static bool const value = has_begin<T>::value && has_end<T>::value; + }; + } + template<typename T> struct is_range : detail::is_range<typename remove_const<T>::type, boost::is_class<T>::value> {}; + template<typename T, typename enable =void> struct range; + template<typename T, typename enable =void> struct iterator; + + template<typename T> + struct iterator<T, typename enable_if<is_range<T> >::type> + { + typedef typename boost::range_iterator<T>::type type; + typedef typename boost::range_iterator<T const>::type const_type; + typedef typename boost::iterator_value<type>::type value_type; + }; + template<typename T> + struct iterator<T*, void> + { + typedef typename remove_const<T>::type value_type; + typedef T* type; + typedef value_type const* const_type; + }; + template<typename T> + struct range_base + { + typedef typename cnv::iterator<T>::value_type value_type; + typedef typename cnv::iterator<T>::type iterator; + typedef typename cnv::iterator<T>::const_type const_iterator; + typedef const_iterator sentry_type; + + range_base (iterator b, iterator e) : begin_(b), end_(e) {} + + iterator begin () { return begin_; } + iterator end () { return end_; } + const_iterator begin () const { return begin_; } + const_iterator end () const { return end_; } + sentry_type sentry () const { return end_; } + void operator++ () { ++begin_; } + void operator-- () { --end_; } + + protected: + + iterator begin_; + mutable iterator end_; + }; + + template<typename T> + struct range<T, typename enable_if<is_range<T> >::type> : public range_base<T> + { + typedef range this_type; + typedef range_base<T> base_type; + + range (T& r) : base_type(r.begin(), r.end()) {} + }; + + template<typename T> + struct range<T*, typename enable_if<cnv::is_char<T> >::type> : public range_base<T*> + { + typedef range this_type; + typedef range_base<T*> base_type; + + typedef typename remove_const<T>::type value_type; + typedef T* iterator; + typedef value_type const* const_iterator; + + struct sentry_type + { + friend bool operator!=(iterator it, sentry_type) { return !!*it; } + }; + + range (iterator b, iterator e =0) : base_type(b, e) {} + + iterator end () { return base_type::end_ ? base_type::end_ : (base_type::end_ = base_type::begin_ + size()); } + const_iterator end () const { return base_type::end_ ? base_type::end_ : (base_type::end_ = base_type::begin_ + size()); } + sentry_type sentry () const { return sentry_type(); } + std::size_t size () const { return std::char_traits<value_type>::length(base_type::begin_); } + }; + template<typename T> + struct range<T* const, void> : public range<T*> + { + range (T* b, T* e =0) : range<T*>(b, e) {} + }; + template <typename T, std::size_t N> + struct range<T [N], void> : public range<T*> + { + range (T* b, T* e =0) : range<T*>(b, e) {} + }; +}} + +#endif // BOOST_CONVERT_DETAIL_RANGE_HPP |