Changeset 80636


Ignore:
Timestamp:
Sep 22, 2012, 7:15:37 PM (6 years ago)
Author:
Eric Niebler
Message:

sfinae-friendly result_of implementation for compilers that don't have extended sfinae for expressions

Location:
trunk/boost/utility
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/boost/utility/detail/result_of_iterate.hpp

    r80608 r80636  
    2424
    2525#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
    26 template<typename F BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
    27          BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
     26template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
    2827struct tr1_result_of<F(BOOST_RESULT_OF_ARGS)>
    2928    : mpl::if_<
    3029          mpl::or_< is_pointer<F>, is_member_function_pointer<F> >
    3130        , boost::detail::tr1_result_of_impl<
    32             typename remove_cv<F>::type, 
    33             typename remove_cv<F>::type(BOOST_RESULT_OF_ARGS), 
     31            typename remove_cv<F>::type,
     32            typename remove_cv<F>::type(BOOST_RESULT_OF_ARGS),
    3433            (boost::detail::has_result_type<F>::value)>
    3534        , boost::detail::tr1_result_of_impl<
    3635            F,
    37             F(BOOST_RESULT_OF_ARGS), 
     36            F(BOOST_RESULT_OF_ARGS),
    3837            (boost::detail::has_result_type<F>::value)> >::type { };
    3938#endif
     
    4241
    4342// Uses declval following N3225 20.7.7.6 when F is not a pointer.
    44 template<typename F BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
    45          BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
     43template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
    4644struct result_of<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T))>
    4745    : mpl::if_<
    4846          is_member_function_pointer<F>
    4947        , detail::tr1_result_of_impl<
    50             typename remove_cv<F>::type, 
     48            typename remove_cv<F>::type,
    5149            typename remove_cv<F>::type(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), false
    5250          >
     
    5957namespace detail {
    6058
    61 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1700))
    62 
    63 template<typename F BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
    64          BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
    65 class is_callable<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T))> {
    66     typedef char (&pass)[1];
    67     typedef char (&fail)[2];
    68 
    69     template<typename G BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
    70              BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename S)>
    71     struct sub {};
    72     template<typename S>
    73     struct stub {};
    74 
    75     template<typename G BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
    76              BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename S)>
    77     static pass test(sub<G BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
    78                          BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),S)>
    79                    , stub<
    80                           decltype(
    81                               boost::declval<G>()(
    82                                   BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval<S, >() BOOST_PP_INTERCEPT)
    83                               )
    84                           )
    85                       >* x = 0);
    86     static fail test(...);
    87 
    88 public:
    89     const static bool value = sizeof(pass) == sizeof(test(sub<F BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
    90                                                               BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)
    91                                                           >()));
    92     typedef typename boost::mpl::bool_<value>::type type;
    93 };
    94 
    95 template<typename F BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
    96          BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
     59#ifdef BOOST_NO_SFINAE_EXPR
     60
     61template<typename F>
     62struct BOOST_PP_CAT(result_of_is_callable_fun_2_, BOOST_PP_ITERATION());
     63
     64template<typename R BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), typename T)>
     65struct BOOST_PP_CAT(result_of_is_callable_fun_2_, BOOST_PP_ITERATION())<R(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), T))> {
     66    R operator()(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), T)) const;
     67    typedef result_of_private_type const &(*pfn_t)(...);
     68    operator pfn_t() const volatile;
     69};
     70
     71template<typename F>
     72struct BOOST_PP_CAT(result_of_is_callable_fun_, BOOST_PP_ITERATION());
     73
     74template<typename F>
     75struct BOOST_PP_CAT(result_of_is_callable_fun_, BOOST_PP_ITERATION())<F *>
     76  : BOOST_PP_CAT(result_of_is_callable_fun_2_, BOOST_PP_ITERATION())<F>
     77{};
     78
     79template<typename F>
     80struct BOOST_PP_CAT(result_of_is_callable_fun_, BOOST_PP_ITERATION())<F &>
     81  : BOOST_PP_CAT(result_of_is_callable_fun_2_, BOOST_PP_ITERATION())<F>
     82{};
     83
     84template<typename F>
     85struct BOOST_PP_CAT(result_of_select_call_wrapper_type_, BOOST_PP_ITERATION())
     86  : mpl::eval_if<
     87        is_class<typename remove_reference<F>::type>,
     88        result_of_wrap_callable<result_of_callable_class, F>,
     89        mpl::identity<BOOST_PP_CAT(result_of_is_callable_fun_, BOOST_PP_ITERATION())<typename remove_cv<F>::type> >
     90    >
     91{};
     92
     93template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), typename T)>
     94struct BOOST_PP_CAT(result_of_is_callable_, BOOST_PP_ITERATION()) {
     95    typedef typename BOOST_PP_CAT(result_of_select_call_wrapper_type_, BOOST_PP_ITERATION())<F>::type wrapper_t;
     96    static const bool value = (
     97        sizeof(result_of_no_type) == sizeof(detail::result_of_is_private_type(
     98            (boost::declval<wrapper_t>()(BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval<T, >() BOOST_PP_INTERCEPT)), 0)
     99        ))
     100    );
     101    typedef mpl::bool_<value> type;
     102};
     103
     104template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
    97105struct cpp0x_result_of_impl<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), true>
    98106    : lazy_enable_if<
    99           is_callable<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T))>
     107          BOOST_PP_CAT(result_of_is_callable_, BOOST_PP_ITERATION())<F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), T)>
    100108        , cpp0x_result_of_impl<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), false>
    101109      >
    102110{};
    103111
    104 template<typename F BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
    105          BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
     112template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
    106113struct cpp0x_result_of_impl<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), false>
    107114{
     
    113120};
    114121
    115 #else // BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1700))
    116 
    117 template<typename F BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
    118          BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
    119 struct cpp0x_result_of_impl<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)),
     122#else // BOOST_NO_SFINAE_EXPR
     123
     124template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
     125struct cpp0x_result_of_impl<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)),
    120126                            typename result_of_always_void<decltype(
    121127                                boost::declval<F>()(
     
    130136};
    131137
    132 #endif // BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1700))
    133 
    134 } // namespace detail 
     138#endif // BOOST_NO_SFINAE_EXPR
     139
     140} // namespace detail
    135141
    136142#else // defined(BOOST_RESULT_OF_USE_DECLTYPE)
    137143
    138144#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
    139 template<typename F BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
    140          BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
     145template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
    141146struct result_of<F(BOOST_RESULT_OF_ARGS)>
    142147    : tr1_result_of<F(BOOST_RESULT_OF_ARGS)> { };
     
    147152#undef BOOST_RESULT_OF_ARGS
    148153
    149 #if BOOST_PP_ITERATION() >= 1 
     154#if BOOST_PP_ITERATION() >= 1
    150155
    151156namespace detail {
    152157
    153 template<typename R,  typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
    154          BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
     158template<typename R,  typename FArgs BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
    155159struct tr1_result_of_impl<R (*)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), FArgs, false>
    156160{
     
    158162};
    159163
    160 template<typename R,  typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
    161          BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
     164template<typename R,  typename FArgs BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
    162165struct tr1_result_of_impl<R (&)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), FArgs, false>
    163166{
     
    166169
    167170#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
    168 template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
    169          BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
     171template<typename R, typename FArgs BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
    170172struct tr1_result_of_impl<R (T0::*)
    171173                     (BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_ITERATION(),T)),
     
    175177};
    176178
    177 template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
    178          BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
     179template<typename R, typename FArgs BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
    179180struct tr1_result_of_impl<R (T0::*)
    180181                     (BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_ITERATION(),T))
     
    185186};
    186187
    187 template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
    188          BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
     188template<typename R, typename FArgs BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
    189189struct tr1_result_of_impl<R (T0::*)
    190190                     (BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_ITERATION(),T))
     
    195195};
    196196
    197 template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
    198          BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
     197template<typename R, typename FArgs BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
    199198struct tr1_result_of_impl<R (T0::*)
    200199                     (BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_ITERATION(),T))
  • trunk/boost/utility/result_of.hpp

    r80605 r80636  
    1111
    1212#include <boost/config.hpp>
    13 #include <boost/preprocessor/iteration/iterate.hpp>
    14 #include <boost/preprocessor/punctuation/comma_if.hpp>
    15 #include <boost/preprocessor/repetition/enum_params.hpp>
    16 #include <boost/preprocessor/repetition/enum_binary_params.hpp>
    17 #include <boost/preprocessor/repetition/enum_shifted_params.hpp>
    18 #include <boost/preprocessor/facilities/intercept.hpp>
     13#include <boost/preprocessor/cat.hpp>
     14#include <boost/preprocessor/iteration/iterate.hpp>
     15#include <boost/preprocessor/repetition/enum_params.hpp>
     16#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
     17#include <boost/preprocessor/repetition/enum_binary_params.hpp>
     18#include <boost/preprocessor/repetition/enum_shifted_params.hpp>
     19#include <boost/preprocessor/facilities/intercept.hpp>
    1920#include <boost/detail/workaround.hpp>
    2021#include <boost/mpl/has_xxx.hpp>
    2122#include <boost/mpl/if.hpp>
     23#include <boost/mpl/eval_if.hpp>
    2224#include <boost/mpl/bool.hpp>
     25#include <boost/mpl/identity.hpp>
    2326#include <boost/mpl/or.hpp>
     27#include <boost/type_traits/is_class.hpp>
    2428#include <boost/type_traits/is_pointer.hpp>
    2529#include <boost/type_traits/is_member_function_pointer.hpp>
    2630#include <boost/type_traits/remove_cv.hpp>
     31#include <boost/type_traits/remove_reference.hpp>
    2732#include <boost/utility/declval.hpp>
    2833#include <boost/utility/enable_if.hpp>
     
    6267template<typename F, typename FArgs, bool HasResultType> struct tr1_result_of_impl;
    6368
    64 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1700))
     69#ifdef BOOST_NO_SFINAE_EXPR
    6570
    66 template<typename F> class is_callable;
     71template<typename T> T result_of_decay(T);
     72
     73struct result_of_private_type
     74{
     75  result_of_private_type const &operator,(int) const;
     76};
     77
     78template<typename C>
     79struct result_of_callable_class : C {
     80    result_of_callable_class();
     81    typedef result_of_private_type const &(*pfn_t)(...);
     82    operator pfn_t() const volatile;
     83};
     84
     85typedef char result_of_yes_type;      // sizeof(result_of_yes_type) == 1
     86typedef char (&result_of_no_type)[2]; // sizeof(result_of_no_type)  == 2
     87
     88template<typename T>
     89result_of_no_type result_of_is_private_type(T const &);
     90
     91result_of_yes_type result_of_is_private_type(result_of_private_type const &);
     92
     93template<template<typename> class Wrapper, typename C>
     94struct result_of_wrap_callable {
     95  typedef Wrapper<C> type;
     96};
     97
     98template<template<typename> class Wrapper, typename C>
     99struct result_of_wrap_callable<Wrapper, C &> {
     100  typedef typename result_of_wrap_callable<Wrapper, C>::type &type;
     101};
     102
     103template<template<typename> class Wrapper, typename C>
     104struct result_of_wrap_callable<Wrapper, C const> {
     105  typedef typename result_of_wrap_callable<Wrapper, C>::type const type;
     106};
     107
     108template<template<typename> class Wrapper, typename C>
     109struct result_of_wrap_callable<Wrapper, C volatile> {
     110  typedef typename result_of_wrap_callable<Wrapper, C>::type volatile type;
     111};
     112
     113template<template<typename> class Wrapper, typename C>
     114struct result_of_wrap_callable<Wrapper, C const volatile> {
     115  typedef typename result_of_wrap_callable<Wrapper, C>::type const volatile type;
     116};
     117
    67118template<typename F, bool TestCallability = true> struct cpp0x_result_of_impl;
    68119
    69 #else // BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1700))
     120#else // BOOST_NO_SFINAE_EXPR
    70121
    71122template<typename T>
    72123struct result_of_always_void
    73124{
    74     typedef void type;
     125  typedef void type;
    75126};
     127
    76128template<typename F, typename Enable = void> struct cpp0x_result_of_impl {};
    77129
    78 #endif // BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1700))
     130#endif // BOOST_NO_SFINAE_EXPR
    79131
    80132template<typename F>
Note: See TracChangeset for help on using the changeset viewer.