diff --git a/include/boost/function/function_base.hpp b/include/boost/function/function_base.hpp index f3663d7..9e01ef9 100644 --- a/include/boost/function/function_base.hpp +++ b/include/boost/function/function_base.hpp @@ -294,7 +294,7 @@ namespace boost { } else if (op == destroy_functor_tag) out_buffer.func_ptr = 0; else if (op == check_functor_type_tag) { - const detail::sp_typeinfo& check_type + const boost::detail::sp_typeinfo& check_type = *out_buffer.type.type; if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_TYPEID(Functor))) out_buffer.obj_ptr = &in_buffer.func_ptr; diff --git a/include/boost/function/function_template.hpp b/include/boost/function/function_template.hpp index 72b7fab..ab7abc5 100644 --- a/include/boost/function/function_template.hpp +++ b/include/boost/function/function_template.hpp @@ -26,7 +26,13 @@ #define BOOST_FUNCTION_PARMS BOOST_PP_ENUM(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_PARM,BOOST_PP_EMPTY) -#define BOOST_FUNCTION_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, a) +#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES +# define BOOST_FUNCTION_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, a) +#else +# include +# define BOOST_FUNCTION_ARG(J,I,D) ::boost::forward< BOOST_PP_CAT(T,I) >(BOOST_PP_CAT(a,I)) +# define BOOST_FUNCTION_ARGS BOOST_PP_ENUM(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_ARG,BOOST_PP_EMPTY) +#endif #define BOOST_FUNCTION_ARG_TYPE(J,I,D) \ typedef BOOST_PP_CAT(T,I) BOOST_PP_CAT(BOOST_PP_CAT(arg, BOOST_PP_INC(I)),_type); @@ -914,10 +920,10 @@ namespace boost { template void assign_to(Functor f) { - using detail::function::vtable_base; + using boost::detail::function::vtable_base; - typedef typename detail::function::get_function_tag::type tag; - typedef detail::function::BOOST_FUNCTION_GET_INVOKER get_invoker; + typedef typename boost::detail::function::get_function_tag::type tag; + typedef boost::detail::function::BOOST_FUNCTION_GET_INVOKER get_invoker; typedef typename get_invoker:: template apply @@ -938,9 +944,9 @@ namespace boost { // coverity[pointless_expression]: suppress coverity warnings on apparant if(const). if (boost::has_trivial_copy_constructor::value && boost::has_trivial_destructor::value && - detail::function::function_allows_small_object_optimization::value) + boost::detail::function::function_allows_small_object_optimization::value) value |= static_cast(0x01); - vtable = reinterpret_cast(value); + vtable = reinterpret_cast(value); } else vtable = 0; } @@ -948,10 +954,10 @@ namespace boost { template void assign_to_a(Functor f,Allocator a) { - using detail::function::vtable_base; + using boost::detail::function::vtable_base; - typedef typename detail::function::get_function_tag::type tag; - typedef detail::function::BOOST_FUNCTION_GET_INVOKER get_invoker; + typedef typename boost::detail::function::get_function_tag::type tag; + typedef boost::detail::function::BOOST_FUNCTION_GET_INVOKER get_invoker; typedef typename get_invoker:: template apply_a::value && boost::has_trivial_destructor::value && - detail::function::function_allows_small_object_optimization::value) + boost::detail::function::function_allows_small_object_optimization::value) value |= static_cast(0x01); - vtable = reinterpret_cast(value); + vtable = reinterpret_cast(value); } else vtable = 0; } @@ -1176,6 +1182,9 @@ public: #undef BOOST_FUNCTION_TEMPLATE_ARGS #undef BOOST_FUNCTION_PARMS #undef BOOST_FUNCTION_PARM +#ifdef BOOST_FUNCTION_ARG +# undef BOOST_FUNCTION_ARG +#endif #undef BOOST_FUNCTION_ARGS #undef BOOST_FUNCTION_ARG_TYPE #undef BOOST_FUNCTION_ARG_TYPES diff --git a/meta/libraries.json b/meta/libraries.json new file mode 100644 index 0000000..9252319 --- /dev/null +++ b/meta/libraries.json @@ -0,0 +1,18 @@ +{ + "key": "function", + "name": "Function", + "authors": [ + "Doug Gregor" + ], + "description": "Function object wrappers for deferred calls or callbacks.", + "std": [ + "tr1" + ], + "category": [ + "Function-objects", + "Programming" + ], + "maintainers": [ + "Douglas Gregor " + ] +} diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 68895fa..5a2dbad 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -61,6 +61,8 @@ import testing ; [ run libs/function/test/nothrow_swap.cpp : : : : ] + [ run libs/function/test/rvalues_test.cpp : : : : ] + [ compile libs/function/test/function_typeof_test.cpp ] ; } diff --git a/test/rvalues_test.cpp b/test/rvalues_test.cpp new file mode 100644 index 0000000..977f4ba --- /dev/null +++ b/test/rvalues_test.cpp @@ -0,0 +1,106 @@ +// Copyright 2014 Antony Polukhin. +// +// 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) + +// For more information, see http://www.boost.org + +#include +#include + +#include +#include +#include + +class only_movable { +private: + BOOST_MOVABLE_BUT_NOT_COPYABLE(only_movable) + int value_; + bool moved_; + +public: + only_movable(BOOST_RV_REF(only_movable) x) + : value_(x.value_) + , moved_(false) + { + x.moved_ = true; + } + + only_movable& operator=(BOOST_RV_REF(only_movable) x) { + value_ = x.value_; + x.moved_ = true; + moved_ = false; + return *this; + } + + explicit only_movable(int value = 0) : value_(value), moved_(false) {} + int get_value() const { return value_; } + bool is_moved() const { return moved_; } +}; + + +int one(BOOST_RV_REF(only_movable) v) { return v.get_value(); } +only_movable two(BOOST_RV_REF(only_movable) t) { + only_movable t1 = boost::move(t); + return BOOST_MOVE_RET(only_movable, t1); +} + +only_movable two_sum(BOOST_RV_REF(only_movable) t1, BOOST_RV_REF(only_movable) t2) { + only_movable ret(t1.get_value() + t2.get_value()); + return BOOST_MOVE_RET(only_movable, ret); +} + +struct sum_struct { + only_movable operator()(BOOST_RV_REF(only_movable) t1, BOOST_RV_REF(only_movable) t2) const { + only_movable ret(t1.get_value() + t2.get_value()); + return BOOST_MOVE_RET(only_movable, ret); + } +}; + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +int three(std::string&&) { return 1; } +std::string&& four(std::string&& s) { return boost::move(s); } +#endif + +int test_main(int, char*[]) +{ + using boost::function; + + function f1 = one; + + only_movable om1(1); + BOOST_CHECK(f1(boost::move(om1)) == 1); + + function f2 = two; + + only_movable om2(2); + only_movable om2_2 = f2(boost::move(om2)); + BOOST_CHECK(om2_2.get_value() == 2); + BOOST_CHECK(om2.is_moved()); + + { + function f2_sum = two_sum; + only_movable om1_sum(1), om2_sum(2); + only_movable om2_sum_2 = f2_sum(boost::move(om1_sum), boost::move(om2_sum)); + BOOST_CHECK(om2_sum_2.get_value() == 3); + } + + { + sum_struct s; + function f2_sum = s; + only_movable om1_sum(1), om2_sum(2); + only_movable om2_sum_2 = f2_sum(boost::move(om1_sum), boost::move(om2_sum)); + BOOST_CHECK(om2_sum_2.get_value() == 3); + } + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + function f3 = three; + function f4 = four; + + f3(std::string("Hello")); + BOOST_CHECK(f4(std::string("world")) == "world"); +#endif + + return 0; +}