Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r80636 - in trunk/boost/utility: . detail
From: eric_at_[hidden]
Date: 2012-09-22 15:15:38


Author: eric_niebler
Date: 2012-09-22 15:15:37 EDT (Sat, 22 Sep 2012)
New Revision: 80636
URL: http://svn.boost.org/trac/boost/changeset/80636

Log:
sfinae-friendly result_of implementation for compilers that don't have extended sfinae for expressions
Text files modified:
   trunk/boost/utility/detail/result_of_iterate.hpp | 129 +++++++++++++++++++--------------------
   trunk/boost/utility/result_of.hpp | 74 +++++++++++++++++++---
   2 files changed, 127 insertions(+), 76 deletions(-)

Modified: trunk/boost/utility/detail/result_of_iterate.hpp
==============================================================================
--- trunk/boost/utility/detail/result_of_iterate.hpp (original)
+++ trunk/boost/utility/detail/result_of_iterate.hpp 2012-09-22 15:15:37 EDT (Sat, 22 Sep 2012)
@@ -23,31 +23,29 @@
 #endif
 
 #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
-template<typename F BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
- BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
+template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
 struct tr1_result_of<F(BOOST_RESULT_OF_ARGS)>
     : mpl::if_<
           mpl::or_< is_pointer<F>, is_member_function_pointer<F> >
         , boost::detail::tr1_result_of_impl<
- typename remove_cv<F>::type,
- typename remove_cv<F>::type(BOOST_RESULT_OF_ARGS),
+ typename remove_cv<F>::type,
+ typename remove_cv<F>::type(BOOST_RESULT_OF_ARGS),
             (boost::detail::has_result_type<F>::value)>
         , boost::detail::tr1_result_of_impl<
             F,
- F(BOOST_RESULT_OF_ARGS),
+ F(BOOST_RESULT_OF_ARGS),
             (boost::detail::has_result_type<F>::value)> >::type { };
 #endif
 
 #ifdef BOOST_RESULT_OF_USE_DECLTYPE
 
 // Uses declval following N3225 20.7.7.6 when F is not a pointer.
-template<typename F BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
- BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
+template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
 struct result_of<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T))>
     : mpl::if_<
           is_member_function_pointer<F>
         , detail::tr1_result_of_impl<
- typename remove_cv<F>::type,
+ typename remove_cv<F>::type,
             typename remove_cv<F>::type(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), false
>
         , detail::cpp0x_result_of_impl<
@@ -58,51 +56,60 @@
 
 namespace detail {
 
-#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1700))
+#ifdef BOOST_NO_SFINAE_EXPR
 
-template<typename F BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
- BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
-class is_callable<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T))> {
- typedef char (&pass)[1];
- typedef char (&fail)[2];
-
- template<typename G BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
- BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename S)>
- struct sub {};
- template<typename S>
- struct stub {};
-
- template<typename G BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
- BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename S)>
- static pass test(sub<G BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
- BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),S)>
- , stub<
- decltype(
- boost::declval<G>()(
- BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval<S, >() BOOST_PP_INTERCEPT)
- )
- )
- >* x = 0);
- static fail test(...);
-
-public:
- const static bool value = sizeof(pass) == sizeof(test(sub<F BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
- BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)
- >()));
- typedef typename boost::mpl::bool_<value>::type type;
+template<typename F>
+struct BOOST_PP_CAT(result_of_is_callable_fun_2_, BOOST_PP_ITERATION());
+
+template<typename R BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), typename T)>
+struct BOOST_PP_CAT(result_of_is_callable_fun_2_, BOOST_PP_ITERATION())<R(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), T))> {
+ R operator()(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), T)) const;
+ typedef result_of_private_type const &(*pfn_t)(...);
+ operator pfn_t() const volatile;
+};
+
+template<typename F>
+struct BOOST_PP_CAT(result_of_is_callable_fun_, BOOST_PP_ITERATION());
+
+template<typename F>
+struct BOOST_PP_CAT(result_of_is_callable_fun_, BOOST_PP_ITERATION())<F *>
+ : BOOST_PP_CAT(result_of_is_callable_fun_2_, BOOST_PP_ITERATION())<F>
+{};
+
+template<typename F>
+struct BOOST_PP_CAT(result_of_is_callable_fun_, BOOST_PP_ITERATION())<F &>
+ : BOOST_PP_CAT(result_of_is_callable_fun_2_, BOOST_PP_ITERATION())<F>
+{};
+
+template<typename F>
+struct BOOST_PP_CAT(result_of_select_call_wrapper_type_, BOOST_PP_ITERATION())
+ : mpl::eval_if<
+ is_class<typename remove_reference<F>::type>,
+ result_of_wrap_callable<result_of_callable_class, F>,
+ mpl::identity<BOOST_PP_CAT(result_of_is_callable_fun_, BOOST_PP_ITERATION())<typename remove_cv<F>::type> >
+ >
+{};
+
+template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), typename T)>
+struct BOOST_PP_CAT(result_of_is_callable_, BOOST_PP_ITERATION()) {
+ typedef typename BOOST_PP_CAT(result_of_select_call_wrapper_type_, BOOST_PP_ITERATION())<F>::type wrapper_t;
+ static const bool value = (
+ sizeof(result_of_no_type) == sizeof(detail::result_of_is_private_type(
+ (boost::declval<wrapper_t>()(BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval<T, >() BOOST_PP_INTERCEPT)), 0)
+ ))
+ );
+ typedef mpl::bool_<value> type;
 };
 
-template<typename F BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
- BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
+template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
 struct cpp0x_result_of_impl<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), true>
     : lazy_enable_if<
- is_callable<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T))>
+ BOOST_PP_CAT(result_of_is_callable_, BOOST_PP_ITERATION())<F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), T)>
         , cpp0x_result_of_impl<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), false>
>
 {};
 
-template<typename F BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
- BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
+template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
 struct cpp0x_result_of_impl<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), false>
 {
   typedef decltype(
@@ -112,11 +119,10 @@
   ) type;
 };
 
-#else // BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1700))
+#else // BOOST_NO_SFINAE_EXPR
 
-template<typename F BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
- BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
-struct cpp0x_result_of_impl<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)),
+template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
+struct cpp0x_result_of_impl<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)),
                             typename result_of_always_void<decltype(
                                 boost::declval<F>()(
                                     BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval<T, >() BOOST_PP_INTERCEPT)
@@ -129,15 +135,14 @@
   ) type;
 };
 
-#endif // BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1700))
+#endif // BOOST_NO_SFINAE_EXPR
 
-} // namespace detail
+} // namespace detail
 
 #else // defined(BOOST_RESULT_OF_USE_DECLTYPE)
 
 #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
-template<typename F BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
- BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
+template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
 struct result_of<F(BOOST_RESULT_OF_ARGS)>
     : tr1_result_of<F(BOOST_RESULT_OF_ARGS)> { };
 #endif
@@ -146,27 +151,24 @@
 
 #undef BOOST_RESULT_OF_ARGS
 
-#if BOOST_PP_ITERATION() >= 1
+#if BOOST_PP_ITERATION() >= 1
 
 namespace detail {
 
-template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
- BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
+template<typename R, typename FArgs BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
 struct tr1_result_of_impl<R (*)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), FArgs, false>
 {
   typedef R type;
 };
 
-template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
- BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
+template<typename R, typename FArgs BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
 struct tr1_result_of_impl<R (&)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), FArgs, false>
 {
   typedef R type;
 };
 
 #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
-template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
- BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
+template<typename R, typename FArgs BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
 struct tr1_result_of_impl<R (T0::*)
                      (BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_ITERATION(),T)),
                  FArgs, false>
@@ -174,8 +176,7 @@
   typedef R type;
 };
 
-template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
- BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
+template<typename R, typename FArgs BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
 struct tr1_result_of_impl<R (T0::*)
                      (BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_ITERATION(),T))
                      const,
@@ -184,8 +185,7 @@
   typedef R type;
 };
 
-template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
- BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
+template<typename R, typename FArgs BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
 struct tr1_result_of_impl<R (T0::*)
                      (BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_ITERATION(),T))
                      volatile,
@@ -194,8 +194,7 @@
   typedef R type;
 };
 
-template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
- BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
+template<typename R, typename FArgs BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
 struct tr1_result_of_impl<R (T0::*)
                      (BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_ITERATION(),T))
                      const volatile,

Modified: trunk/boost/utility/result_of.hpp
==============================================================================
--- trunk/boost/utility/result_of.hpp (original)
+++ trunk/boost/utility/result_of.hpp 2012-09-22 15:15:37 EDT (Sat, 22 Sep 2012)
@@ -10,20 +10,25 @@
 #define BOOST_RESULT_OF_HPP
 
 #include <boost/config.hpp>
-#include <boost/preprocessor/iteration/iterate.hpp>
-#include <boost/preprocessor/punctuation/comma_if.hpp>
-#include <boost/preprocessor/repetition/enum_params.hpp>
-#include <boost/preprocessor/repetition/enum_binary_params.hpp>
-#include <boost/preprocessor/repetition/enum_shifted_params.hpp>
-#include <boost/preprocessor/facilities/intercept.hpp>
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/iteration/iterate.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
+#include <boost/preprocessor/repetition/enum_binary_params.hpp>
+#include <boost/preprocessor/repetition/enum_shifted_params.hpp>
+#include <boost/preprocessor/facilities/intercept.hpp>
 #include <boost/detail/workaround.hpp>
 #include <boost/mpl/has_xxx.hpp>
 #include <boost/mpl/if.hpp>
+#include <boost/mpl/eval_if.hpp>
 #include <boost/mpl/bool.hpp>
+#include <boost/mpl/identity.hpp>
 #include <boost/mpl/or.hpp>
+#include <boost/type_traits/is_class.hpp>
 #include <boost/type_traits/is_pointer.hpp>
 #include <boost/type_traits/is_member_function_pointer.hpp>
 #include <boost/type_traits/remove_cv.hpp>
+#include <boost/type_traits/remove_reference.hpp>
 #include <boost/utility/declval.hpp>
 #include <boost/utility/enable_if.hpp>
 
@@ -61,21 +66,68 @@
 
 template<typename F, typename FArgs, bool HasResultType> struct tr1_result_of_impl;
 
-#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1700))
+#ifdef BOOST_NO_SFINAE_EXPR
+
+template<typename T> T result_of_decay(T);
+
+struct result_of_private_type
+{
+ result_of_private_type const &operator,(int) const;
+};
+
+template<typename C>
+struct result_of_callable_class : C {
+ result_of_callable_class();
+ typedef result_of_private_type const &(*pfn_t)(...);
+ operator pfn_t() const volatile;
+};
+
+typedef char result_of_yes_type; // sizeof(result_of_yes_type) == 1
+typedef char (&result_of_no_type)[2]; // sizeof(result_of_no_type) == 2
+
+template<typename T>
+result_of_no_type result_of_is_private_type(T const &);
+
+result_of_yes_type result_of_is_private_type(result_of_private_type const &);
+
+template<template<typename> class Wrapper, typename C>
+struct result_of_wrap_callable {
+ typedef Wrapper<C> type;
+};
+
+template<template<typename> class Wrapper, typename C>
+struct result_of_wrap_callable<Wrapper, C &> {
+ typedef typename result_of_wrap_callable<Wrapper, C>::type &type;
+};
+
+template<template<typename> class Wrapper, typename C>
+struct result_of_wrap_callable<Wrapper, C const> {
+ typedef typename result_of_wrap_callable<Wrapper, C>::type const type;
+};
+
+template<template<typename> class Wrapper, typename C>
+struct result_of_wrap_callable<Wrapper, C volatile> {
+ typedef typename result_of_wrap_callable<Wrapper, C>::type volatile type;
+};
+
+template<template<typename> class Wrapper, typename C>
+struct result_of_wrap_callable<Wrapper, C const volatile> {
+ typedef typename result_of_wrap_callable<Wrapper, C>::type const volatile type;
+};
 
-template<typename F> class is_callable;
 template<typename F, bool TestCallability = true> struct cpp0x_result_of_impl;
 
-#else // BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1700))
+#else // BOOST_NO_SFINAE_EXPR
 
 template<typename T>
 struct result_of_always_void
 {
- typedef void type;
+ typedef void type;
 };
+
 template<typename F, typename Enable = void> struct cpp0x_result_of_impl {};
 
-#endif // BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1700))
+#endif // BOOST_NO_SFINAE_EXPR
 
 template<typename F>
 struct result_of_void_impl


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk