Ticket #4803: djw_function_static_empty.patch

File djw_function_static_empty.patch, 23.0 KB (added by Daniel Walker, 12 years ago)

Implements BOOST_FUNCTION_USE_STATIC_EMPTY config macro with tests and docs.

  • boost/function/function_template.hpp

     
    6969#define BOOST_FUNCTION_GET_INVOKER \
    7070  BOOST_JOIN(get_invoker,BOOST_FUNCTION_NUM_ARGS)
    7171#define BOOST_FUNCTION_VTABLE BOOST_JOIN(basic_vtable,BOOST_FUNCTION_NUM_ARGS)
     72#define BOOST_FUNCTION_EMPTY_FUNCTION \
     73  BOOST_JOIN(empty_function, BOOST_FUNCTION_NUM_ARGS)
    7274
    7375#ifndef BOOST_NO_VOID_RETURNS
    7476#  define BOOST_FUNCTION_VOID_RETURN_TYPE void
     
    7981#endif
    8082
    8183namespace boost {
     84#ifdef BOOST_FUNCTION_USE_STATIC_EMPTY
     85  template<
     86    typename R BOOST_FUNCTION_COMMA
     87    BOOST_FUNCTION_TEMPLATE_PARMS
     88  >
     89  class BOOST_FUNCTION_FUNCTION;
     90
     91# if !defined(BOOST_NO_SFINAE)
     92  template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
     93  inline bool operator==(const BOOST_FUNCTION_FUNCTION<
     94                                 R BOOST_FUNCTION_COMMA
     95                                 BOOST_FUNCTION_TEMPLATE_ARGS>& f,
     96                         detail::function::useless_clear_type*)
     97  {
     98    return f.empty();
     99  }
     100
     101  template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
     102  inline bool operator!=(const BOOST_FUNCTION_FUNCTION<
     103                                 R BOOST_FUNCTION_COMMA
     104                                 BOOST_FUNCTION_TEMPLATE_ARGS>& f,
     105                         detail::function::useless_clear_type*)
     106  {
     107    return !f.empty();
     108  }
     109
     110  template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
     111  inline bool operator==(detail::function::useless_clear_type*,
     112                         const BOOST_FUNCTION_FUNCTION<
     113                                 R BOOST_FUNCTION_COMMA
     114                                 BOOST_FUNCTION_TEMPLATE_ARGS>& f)
     115  {
     116    return f.empty();
     117  }
     118
     119  template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
     120  inline bool operator!=(detail::function::useless_clear_type*,
     121                         const BOOST_FUNCTION_FUNCTION<
     122                                 R BOOST_FUNCTION_COMMA
     123                                 BOOST_FUNCTION_TEMPLATE_ARGS>& f)
     124  {
     125    return !f.empty();
     126  }
     127# endif // !defined(BOOST_NO_SFINAE)
     128
    82129  namespace detail {
    83130    namespace function {
     131      template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
     132      inline bool has_empty_target(const BOOST_FUNCTION_FUNCTION<
     133                                     R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS
     134                                   >* f)
     135      {
     136        return f->empty();
     137      }
     138
    84139      template<
     140        typename R BOOST_FUNCTION_COMMA
     141        BOOST_FUNCTION_TEMPLATE_PARMS
     142      >
     143      R BOOST_FUNCTION_EMPTY_FUNCTION(BOOST_FUNCTION_PARMS)
     144      {
     145        BOOST_FUNCTION_RETURN(boost::throw_exception(bad_function_call()));
     146      }
     147    } // namespace function
     148  } // namespace detail
     149#endif // BOOST_FUNCTION_USE_STATIC_EMPTY
     150
     151  namespace detail {
     152    namespace function {
     153      template<
    85154        typename FunctionPtr,
    86155        typename R BOOST_FUNCTION_COMMA
    87156        BOOST_FUNCTION_TEMPLATE_PARMS
     
    486555                                            BOOST_FUNCTION_TEMPLATE_ARGS);
    487556
    488557        template<typename F>
    489         bool assign_to(F f, function_buffer& functor)
     558        bool assign_to(F f, function_buffer& functor) const
    490559        {
    491560          typedef typename get_function_tag<F>::type tag;
    492561          return assign_to(f, functor, tag());
    493562        }
    494563        template<typename F,typename Allocator>
    495         bool assign_to_a(F f, function_buffer& functor, Allocator a)
     564        bool assign_to_a(F f, function_buffer& functor, Allocator a) const
    496565        {
    497566          typedef typename get_function_tag<F>::type tag;
    498567          return assign_to_a(f, functor, a, tag());
    499568        }
    500569
    501         void clear(function_buffer& functor)
     570        void clear(function_buffer& functor) const
    502571        {
    503572          if (base.manager)
    504573            base.manager(functor, functor, destroy_functor_tag);
     
    508577        // Function pointers
    509578        template<typename FunctionPtr>
    510579        bool
    511         assign_to(FunctionPtr f, function_buffer& functor, function_ptr_tag)
     580        assign_to(FunctionPtr f, function_buffer& functor, function_ptr_tag) const
    512581        {
    513582          this->clear(functor);
    514583          if (f) {
     
    522591        }
    523592        template<typename FunctionPtr,typename Allocator>
    524593        bool
    525         assign_to_a(FunctionPtr f, function_buffer& functor, Allocator, function_ptr_tag)
     594        assign_to_a(FunctionPtr f, function_buffer& functor, Allocator, function_ptr_tag) const
    526595        {
    527596          return assign_to(f,functor,function_ptr_tag());
    528597        }
     
    530599        // Member pointers
    531600#if BOOST_FUNCTION_NUM_ARGS > 0
    532601        template<typename MemberPtr>
    533         bool assign_to(MemberPtr f, function_buffer& functor, member_ptr_tag)
     602        bool assign_to(MemberPtr f, function_buffer& functor, member_ptr_tag) const
    534603        {
    535604          // DPG TBD: Add explicit support for member function
    536605          // objects, so we invoke through mem_fn() but we retain the
     
    543612          }
    544613        }
    545614        template<typename MemberPtr,typename Allocator>
    546         bool assign_to_a(MemberPtr f, function_buffer& functor, Allocator a, member_ptr_tag)
     615        bool assign_to_a(MemberPtr f, function_buffer& functor, Allocator a, member_ptr_tag) const
    547616        {
    548617          // DPG TBD: Add explicit support for member function
    549618          // objects, so we invoke through mem_fn() but we retain the
     
    561630        // Assign to a function object using the small object optimization
    562631        template<typename FunctionObj>
    563632        void
    564         assign_functor(FunctionObj f, function_buffer& functor, mpl::true_)
     633        assign_functor(FunctionObj f, function_buffer& functor, mpl::true_) const
    565634        {
    566635          new (reinterpret_cast<void*>(&functor.data)) FunctionObj(f);
    567636        }
    568637        template<typename FunctionObj,typename Allocator>
    569638        void
    570         assign_functor_a(FunctionObj f, function_buffer& functor, Allocator, mpl::true_)
     639        assign_functor_a(FunctionObj f, function_buffer& functor, Allocator, mpl::true_) const
    571640        {
    572641          assign_functor(f,functor,mpl::true_());
    573642        }
     
    575644        // Assign to a function object allocated on the heap.
    576645        template<typename FunctionObj>
    577646        void
    578         assign_functor(FunctionObj f, function_buffer& functor, mpl::false_)
     647        assign_functor(FunctionObj f, function_buffer& functor, mpl::false_) const
    579648        {
    580649          functor.obj_ptr = new FunctionObj(f);
    581650        }
    582651        template<typename FunctionObj,typename Allocator>
    583652        void
    584         assign_functor_a(FunctionObj f, function_buffer& functor, Allocator a, mpl::false_)
     653        assign_functor_a(FunctionObj f, function_buffer& functor, Allocator a, mpl::false_) const
    585654        {
    586655          typedef functor_wrapper<FunctionObj,Allocator> functor_wrapper_type;
    587656          typedef typename Allocator::template rebind<functor_wrapper_type>::other
     
    596665
    597666        template<typename FunctionObj>
    598667        bool
    599         assign_to(FunctionObj f, function_buffer& functor, function_obj_tag)
     668        assign_to(FunctionObj f, function_buffer& functor, function_obj_tag) const
    600669        {
    601670          if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
    602671            assign_functor(f, functor,
     
    608677        }
    609678        template<typename FunctionObj,typename Allocator>
    610679        bool
    611         assign_to_a(FunctionObj f, function_buffer& functor, Allocator a, function_obj_tag)
     680        assign_to_a(FunctionObj f, function_buffer& functor, Allocator a, function_obj_tag) const
    612681        {
    613682          if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
    614683            assign_functor_a(f, functor, a,
     
    623692        template<typename FunctionObj>
    624693        bool
    625694        assign_to(const reference_wrapper<FunctionObj>& f,
    626                   function_buffer& functor, function_obj_ref_tag)
     695                  function_buffer& functor, function_obj_ref_tag) const
    627696        {
    628697          functor.obj_ref.obj_ptr = (void *)(f.get_pointer());
    629698          functor.obj_ref.is_const_qualified = is_const<FunctionObj>::value;
     
    633702        template<typename FunctionObj,typename Allocator>
    634703        bool
    635704        assign_to_a(const reference_wrapper<FunctionObj>& f,
    636                   function_buffer& functor, Allocator, function_obj_ref_tag)
     705                  function_buffer& functor, Allocator, function_obj_ref_tag) const
    637706        {
    638707          return assign_to(f,functor,function_obj_ref_tag());
    639708        }
     
    682751
    683752    struct clear_type {};
    684753
     754    typedef R (*empty_function_type)(BOOST_FUNCTION_TEMPLATE_ARGS);
     755
    685756  public:
    686757    BOOST_STATIC_CONSTANT(int, args = BOOST_FUNCTION_NUM_ARGS);
    687758
     
    704775
    705776    typedef BOOST_FUNCTION_FUNCTION self_type;
    706777
    707     BOOST_FUNCTION_FUNCTION() : function_base() { }
     778    BOOST_FUNCTION_FUNCTION() : function_base()
     779    {
     780#ifdef BOOST_FUNCTION_USE_STATIC_EMPTY
     781      this->assign_empty();
     782#endif
     783    }
    708784
    709785    // MSVC chokes if the following two constructors are collapsed into
    710786    // one with a default parameter.
     
    736812    }
    737813
    738814#ifndef BOOST_NO_SFINAE
    739     BOOST_FUNCTION_FUNCTION(clear_type*) : function_base() { }
     815    BOOST_FUNCTION_FUNCTION(clear_type*) : function_base()
     816    {
     817# ifdef BOOST_FUNCTION_USE_STATIC_EMPTY
     818      this->assign_empty();
     819# endif
     820    }
    740821#else
    741822    BOOST_FUNCTION_FUNCTION(int zero) : function_base()
    742823    {
    743824      BOOST_ASSERT(zero == 0);
     825# ifdef BOOST_FUNCTION_USE_STATIC_EMPTY
     826      this->assign_empty();
     827# endif
    744828    }
    745829#endif
    746830
     
    756840    // these definitions can become very costly.
    757841    result_type operator()(BOOST_FUNCTION_PARMS) const
    758842    {
     843# ifdef BOOST_FUNCTION_USE_STATIC_EMPTY
     844      BOOST_ASSERT(vtable);
     845# else
    759846      if (this->empty())
    760847        boost::throw_exception(bad_function_call());
     848# endif
    761849
    762850      return get_vtable()->invoker
    763851               (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
     
    786874      BOOST_TRY  {
    787875        this->assign_to(f);
    788876      } BOOST_CATCH (...) {
     877#ifdef BOOST_FUNCTION_USE_STATIC_EMPTY
     878        this->assign_empty();
     879#else
    789880        vtable = 0;
     881#endif
    790882        BOOST_RETHROW;
    791883      }
    792884      BOOST_CATCH_END
     
    799891      BOOST_TRY{
    800892        this->assign_to_a(f,a);
    801893      } BOOST_CATCH (...) {
     894#ifdef BOOST_FUNCTION_USE_STATIC_EMPTY
     895        this->assign_empty();
     896#else
    802897        vtable = 0;
     898#endif
    803899        BOOST_RETHROW;
    804900      }
    805901      BOOST_CATCH_END
     
    830926      BOOST_TRY {
    831927        this->assign_to_own(f);
    832928      } BOOST_CATCH (...) {
     929#ifdef BOOST_FUNCTION_USE_STATIC_EMPTY
     930        this->assign_empty();
     931#else
    833932        vtable = 0;
     933#endif
    834934        BOOST_RETHROW;
    835935      }
    836936      BOOST_CATCH_END
     
    848948      other.move_assign(tmp);
    849949    }
    850950
     951#ifdef BOOST_FUNCTION_USE_STATIC_EMPTY
     952    // Determine if the function is empty (i.e., has no target).
     953    bool empty() const
     954    {
     955      empty_function_type const* ptr = target<empty_function_type>();
     956      empty_function_type empty_ptr = &detail::function::BOOST_FUNCTION_EMPTY_FUNCTION<
     957              R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>;
     958      return ptr ? *ptr == empty_ptr : false;
     959    }
     960
    851961    // Clear out a target, if there is one
    852962    void clear()
    853963    {
     964      if (!this->empty()) {
     965        if (!this->has_trivial_copy_and_destroy())
     966          get_vtable()->clear(this->functor);
     967        this->assign_empty();
     968      }
     969    }
     970#else // BOOST_FUNCTION_USE_STATIC_EMPTY
     971    // Clear out a target, if there is one
     972    void clear()
     973    {
    854974      if (vtable) {
    855975        if (!this->has_trivial_copy_and_destroy())
    856976          get_vtable()->clear(this->functor);
    857977        vtable = 0;
    858978      }
    859979    }
     980#endif // BOOST_FUNCTION_USE_STATIC_EMPTY
    860981
    861982#if (defined __SUNPRO_CC) && (__SUNPRO_CC <= 0x530) && !(defined BOOST_NO_COMPILER_CONFIG)
    862983    // Sun C++ 5.3 can't handle the safe_bool idiom, so don't use it
     
    8881009          get_vtable()->base.manager(f.functor, this->functor,
    8891010                                     boost::detail::function::clone_functor_tag);
    8901011      }
     1012#ifdef BOOST_FUNCTION_USE_STATIC_EMPTY
     1013      else
     1014          this->assign_empty();
     1015#endif
    8911016    }
    8921017
    8931018    template<typename Functor>
     
    9091034      // static initialization. Otherwise, we will have a race
    9101035      // condition here in multi-threaded code. See
    9111036      // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/.
    912       static vtable_type stored_vtable =
     1037      static const vtable_type stored_vtable =
    9131038        { { &manager_type::manage }, &invoker_type::invoke };
    9141039
    9151040      if (stored_vtable.assign_to(f, functor)) {
     
    9201045          value |= static_cast<size_t>(0x01);
    9211046        vtable = reinterpret_cast<detail::function::vtable_base *>(value);
    9221047      } else
     1048#ifdef BOOST_FUNCTION_USE_STATIC_EMPTY
     1049        this->assign_empty();
     1050#else
    9231051        vtable = 0;
     1052#endif
    9241053    }
    9251054
    9261055    template<typename Functor,typename Allocator>
     
    9431072      // static initialization. Otherwise, we will have a race
    9441073      // condition here in multi-threaded code. See
    9451074      // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/.
    946       static vtable_type stored_vtable =
     1075      static const vtable_type stored_vtable =
    9471076        { { &manager_type::manage }, &invoker_type::invoke };
    9481077
    9491078      if (stored_vtable.assign_to_a(f, functor, a)) {
     
    9541083          value |= static_cast<std::size_t>(0x01);
    9551084        vtable = reinterpret_cast<detail::function::vtable_base *>(value);
    9561085      } else
     1086#ifdef BOOST_FUNCTION_USE_STATIC_EMPTY
     1087        this->assign_empty();
     1088#else
    9571089        vtable = 0;
     1090#endif
    9581091    }
    9591092
    9601093    // Moves the value from the specified argument to *this. If the argument
     
    9731106          else
    9741107            get_vtable()->base.manager(f.functor, this->functor,
    9751108                                     boost::detail::function::move_functor_tag);
     1109#ifdef BOOST_FUNCTION_USE_STATIC_EMPTY
     1110          f.assign_empty();
     1111#else
    9761112          f.vtable = 0;
     1113#endif
    9771114        } else {
    9781115          clear();
    9791116        }
    9801117      } BOOST_CATCH (...) {
     1118#ifdef BOOST_FUNCTION_USE_STATIC_EMPTY
     1119        this->assign_empty();
     1120#else
    9811121        vtable = 0;
     1122#endif
    9821123        BOOST_RETHROW;
    9831124      }
    9841125      BOOST_CATCH_END
    9851126    }
     1127#ifdef BOOST_FUNCTION_USE_STATIC_EMPTY
     1128    void assign_empty()
     1129    {
     1130      this->assign_to(
     1131          &detail::function::BOOST_FUNCTION_EMPTY_FUNCTION<
     1132            R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
     1133      );
     1134    }
     1135
     1136    void assign_to(empty_function_type f)
     1137    {
     1138      using detail::function::vtable_base;
     1139
     1140      typedef typename detail::function::get_function_tag<empty_function_type>::type tag;
     1141      typedef detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker;
     1142      typedef typename get_invoker::
     1143                         template apply<empty_function_type, R BOOST_FUNCTION_COMMA
     1144                        BOOST_FUNCTION_TEMPLATE_ARGS>
     1145        handler_type;
     1146     
     1147      typedef typename handler_type::invoker_type invoker_type;
     1148      typedef typename handler_type::manager_type manager_type;
     1149
     1150      // Note: it is extremely important that this initialization use
     1151      // static initialization. Otherwise, we will have a race
     1152      // condition here in multi-threaded code. See
     1153      // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/.
     1154      static const vtable_type stored_vtable =
     1155        { { &manager_type::manage }, &invoker_type::invoke };
     1156
     1157      // The following replicates the usual function pointer
     1158      // assignment, which should always succeed for empty_function_type.
     1159      const bool success = stored_vtable.assign_to(f, functor);
     1160      BOOST_ASSERT(success);
     1161      (void) success; // suppress unused variable warning
     1162      std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base);
     1163      value |= static_cast<size_t>(0x01);
     1164      vtable = reinterpret_cast<detail::function::vtable_base *>(value);
     1165    }
     1166#endif // BOOST_FUNCTION_USE_STATIC_EMPTY
    9861167  };
    9871168
    9881169  template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
     
    10061187  BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
    10071188  ::operator()(BOOST_FUNCTION_PARMS) const
    10081189  {
     1190# ifdef BOOST_FUNCTION_USE_STATIC_EMPTY
     1191    BOOST_ASSERT(vtable);
     1192# else
    10091193    if (this->empty())
    10101194      boost::throw_exception(bad_function_call());
     1195# endif
    10111196
    10121197    return get_vtable()->invoker
    10131198             (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
     
    11271312} // end namespace boost
    11281313
    11291314// Cleanup after ourselves...
     1315#undef BOOST_FUNCTION_EMPTY_FUNCTION
    11301316#undef BOOST_FUNCTION_VTABLE
    11311317#undef BOOST_FUNCTION_COMMA
    11321318#undef BOOST_FUNCTION_FUNCTION
  • libs/function/test/Jamfile.v2

     
    2020  test-suite function
    2121    :
    2222  [ run libs/function/test/function_test.cpp :  :  :  : lib_function_test ]
     23  [ run libs/function/test/function_test.cpp :  :  : <define>BOOST_FUNCTION_USE_STATIC_EMPTY : lib_function_test_static_empty ]
    2324
    2425  [ run libs/function/test/function_n_test.cpp :  :  :  :  ]
     26  [ run libs/function/test/function_n_test.cpp :  :  : <define>BOOST_FUNCTION_USE_EMPTY :  function_n_test_static_empty ]
    2527
    2628  [ run libs/function/test/allocator_test.cpp ../../../libs/test/build//boost_test_exec_monitor :  :  :  :  ]
     29  [ run libs/function/test/allocator_test.cpp ../../../libs/test/build//boost_test_exec_monitor :  :  : <define>BOOST_FUNCTION_USE_STATIC_EMPTY : allocator_test_static_empty ]
    2730
    2831  [ run libs/function/test/stateless_test.cpp ../../../libs/test/build//boost_test_exec_monitor :  :  :  :  ]
     32  [ run libs/function/test/stateless_test.cpp ../../../libs/test/build//boost_test_exec_monitor :  :  : <define>BOOST_FUNCTION_USE_STATIC_EMPTY : stateless_test_static_empty ]
    2933
    3034  [ run libs/function/test/lambda_test.cpp ../../../libs/test/build//boost_test_exec_monitor :  :  :  :  ]
     35  [ run libs/function/test/lambda_test.cpp ../../../libs/test/build//boost_test_exec_monitor :  :  : <define>BOOST_FUNCTION_USE_STATIC_EMPTY : lambda_test_static_empty ]
    3136
    3237  [ compile-fail libs/function/test/function_test_fail1.cpp :  :  :  :  ]
     38  [ compile-fail libs/function/test/function_test_fail1.cpp : <define>BOOST_FUNCTION_USE_STATIC_EMPTY : function_test_fail1_static_empty ]
    3339
    3440  [ compile-fail libs/function/test/function_test_fail2.cpp :  :  :  :  ]
     41  [ compile-fail libs/function/test/function_test_fail2.cpp : <define>BOOST_FUNCTION_USE_STATIC_EMPTY : function_test_fail2_static_empty ]
    3542
    3643  [ compile libs/function/test/function_30.cpp :  :  :  :  ]
     44  [ compile libs/function/test/function_30.cpp : <define>BOOST_FUNCTION_USE_STATIC_EMPTY : function_30_static_empty ]
    3745
    3846  [ run libs/function/test/function_arith_cxx98.cpp :  :  :  :  ]
     47  [ run libs/function/test/function_arith_cxx98.cpp :  :  : <define>BOOST_FUNCTION_USE_STATIC_EMPTY : function_arith_cxx98_static_empty ]
    3948
    4049  [ run libs/function/test/function_arith_portable.cpp :  :  :  :  ]
     50  [ run libs/function/test/function_arith_portable.cpp :  :  : <define>BOOST_FUNCTION_USE_STATIC_EMPTY : function_arith_portable_static_empty ]
    4151
    4252  [ run libs/function/test/sum_avg_cxx98.cpp :  :  :  :  ]
     53  [ run libs/function/test/sum_avg_cxx98.cpp :  :  : <define>BOOST_FUNCTION_USE_STATIC_EMPTY : sum_avg_cxx98_static_empty ]
    4354
    4455  [ run libs/function/test/sum_avg_portable.cpp :  :  :  :  ]
     56  [ run libs/function/test/sum_avg_portable.cpp :  :  : <define>BOOST_FUNCTION_USE_STATIC_EMPTY : sum_avg_portable_static_empty ]
    4557
    4658  [ run libs/function/test/mem_fun_cxx98.cpp :  :  :  :  ]
     59  [ run libs/function/test/mem_fun_cxx98.cpp :  :  : <define>BOOST_FUNCTION_USE_STATIC_EMPTY : mem_fun_cxx98_static_empty ]
    4760
    4861  [ run libs/function/test/mem_fun_portable.cpp :  :  :  :  ]
     62  [ run libs/function/test/mem_fun_portable.cpp :  :  : <define>BOOST_FUNCTION_USE_STATIC_EMPTY : mem_fun_portable_static_empty ]
    4963
    5064  [ run libs/function/test/std_bind_cxx98.cpp :  :  :  :  ]
     65  [ run libs/function/test/std_bind_cxx98.cpp :  :  : <define>BOOST_FUNCTION_USE_STATIC_EMPTY : std_bind_cxx98_static_empty ]
    5166
    5267  [ run libs/function/test/std_bind_portable.cpp :  :  :  :  ]
     68  [ run libs/function/test/std_bind_portable.cpp :  :  : <define>BOOST_FUNCTION_USE_STATIC_EMPTY : std_bind_portable_static_empty ]
    5369
    5470  [ run libs/function/test/function_ref_cxx98.cpp :  :  :  :  ]
     71  [ run libs/function/test/function_ref_cxx98.cpp :  :  : <define>BOOST_FUNCTION_USE_STATIC_EMPTY : function_ref_cxx98_static_empty ]
    5572
    5673  [ run libs/function/test/function_ref_portable.cpp :  :  :  :  ]
     74  [ run libs/function/test/function_ref_portable.cpp :  :  : <define>BOOST_FUNCTION_USE_STATIC_EMPTY : function_ref_portable_static_empty ]
    5775 
    5876  [ run libs/function/test/contains_test.cpp : : : : ]
     77  [ run libs/function/test/contains_test.cpp : : : <define>BOOST_FUNCTION_USE_STATIC_EMPTY : contains_test_static_empty ]
    5978   
    6079  [ run libs/function/test/contains2_test.cpp : : : : ]
     80  [ run libs/function/test/contains2_test.cpp : : : <define>BOOST_FUNCTION_USE_STATIC_EMPTY : contains2_test_static_empty ]
    6181   
    6282  [ run libs/function/test/nothrow_swap.cpp :  :  :  :  ]
     83  [ run libs/function/test/nothrow_swap.cpp :  :  : <define>BOOST_FUNCTION_USE_STATIC_EMPTY : nothrow_swap_static_empty ]
    6384
    6485  [ compile libs/function/test/function_typeof_test.cpp ]
     86  [ compile libs/function/test/function_typeof_test.cpp : <define>BOOST_FUNCTION_USE_STATIC_EMPTY : function_typeof_test_static_empty ]
    6587 ;
    6688}
    6789     
  • libs/function/doc/faq.xml

     
    145145    <answer>
    146146      <para>The cost of <code>boost::function</code> can be reasonably
    147147      consistently measured at around 20ns +/- 10 ns on a modern >2GHz
    148       platform versus directly inlining the code.</para>
     148      platform versus directly inlining the code.*</para>
    149149
    150150      <para>However, the performance of your application may benefit
    151151      from or be disadvantaged by <code>boost::function</code>
     
    154154      noted to the benefit or disadvantage of using
    155155      <code>boost::function</code> to call a function that contains a
    156156      tight loop depending on your compilation circumstances.</para>
    157      
    158       <para>[Answer provided by Matt Hurd. See <ulink url="http://article.gmane.org/gmane.comp.lib.boost.devel/33278"/>]</para>
     157
     158      <para>By defining the macro
     159      BOOST_FUNCTION_USE_STATIC_EMPTY, <code>boost::function</code>
     160      can be configured to store static "empty" objects (one per call
     161      signature) which may improve performance depending on your
     162      optimiser at the cost of an increase in the text segment size
     163      of the executable.</para>
     164
     165      <para>*[Answer provided by Matt Hurd. See <ulink url="http://article.gmane.org/gmane.comp.lib.boost.devel/33278"/>]</para>
    159166    </answer>
    160167  </qandaentry>
    161168</qandaset>