diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index cb9ce5545a6..4605d04e6bb 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,14 @@ +2009-12-15 Jonathan Wakely + + * include/std/functional (function::function): Move construct target. + (function::operator=): Use perfect forwarding for argument. + (function::operator()): Use new __throw_bad_function_call. + * include/bits/functexcept.h (__throw_bad_function_call): Declare. + * src/functexcept.cc (__throw_bad_function_call): Define. + * config/abi/pre/gnu.ver: Add new symbol. + * testsuite/20_util/function/cons/move_target.cc: New. + * testsuite/20_util/function/assign/move_target.cc: New. + 2009-12-15 Paolo Carlini PR c++/42379 diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver index 4ed1cfeb2cd..c40288a4b6b 100644 --- a/libstdc++-v3/config/abi/pre/gnu.ver +++ b/libstdc++-v3/config/abi/pre/gnu.ver @@ -1068,6 +1068,8 @@ GLIBCXX_3.4.14 { _ZNSs18_S_construct_aux_2*; _ZNSbIwSt11char_traitsIwESaIwEE18_S_construct_aux_2*; + _ZSt25__throw_bad_function_callv; + } GLIBCXX_3.4.13; # Symbols in the support library (libsupc++) have their own tag. diff --git a/libstdc++-v3/include/bits/functexcept.h b/libstdc++-v3/include/bits/functexcept.h index 62174819118..5b2e9fc0455 100644 --- a/libstdc++-v3/include/bits/functexcept.h +++ b/libstdc++-v3/include/bits/functexcept.h @@ -91,6 +91,10 @@ _GLIBCXX_BEGIN_NAMESPACE(std) void __throw_future_error(int) __attribute__((__noreturn__)); + // Helpers for exception objects in + void + __throw_bad_function_call() __attribute__((__noreturn__)); + _GLIBCXX_END_NAMESPACE #endif diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional index eb10b348ad1..19503bdf05e 100644 --- a/libstdc++-v3/include/std/functional +++ b/libstdc++-v3/include/std/functional @@ -1571,8 +1571,8 @@ namespace std } static void - _M_init_functor(_Any_data& __functor, const _Functor& __f) - { _M_init_functor(__functor, __f, _Local_storage()); } + _M_init_functor(_Any_data& __functor, _Functor&& __f) + { _M_init_functor(__functor, std::move(__f), _Local_storage()); } template static bool @@ -1595,13 +1595,13 @@ namespace std { return true; } private: - static void - _M_init_functor(_Any_data& __functor, const _Functor& __f, true_type) - { new (__functor._M_access()) _Functor(__f); } + static void + _M_init_functor(_Any_data& __functor, _Functor&& __f, true_type) + { new (__functor._M_access()) _Functor(std::move(__f)); } static void - _M_init_functor(_Any_data& __functor, const _Functor& __f, false_type) - { __functor._M_access<_Functor*>() = new _Functor(__f); } + _M_init_functor(_Any_data& __functor, _Functor&& __f, false_type) + { __functor._M_access<_Functor*>() = new _Functor(std::move(__f)); } }; template @@ -1927,9 +1927,9 @@ namespace std template typename __gnu_cxx::__enable_if::value, function&>::__type - operator=(_Functor __f) + operator=(_Functor&& __f) { - function(__f).swap(*this); + function(std::forward<_Functor>(__f)).swap(*this); return *this; } @@ -1969,9 +1969,10 @@ namespace std /* template void - assign(_Functor __f, const _Alloc& __a) + assign(_Functor&& __f, const _Alloc& __a) { - function(__f, __a).swap(*this); + function(allocator_arg, __a, + std::forward<_Functor>(__f)).swap(*this); } */ @@ -2066,7 +2067,7 @@ namespace std { _M_invoker = &_My_handler::_M_invoke; _M_manager = &_My_handler::_M_manager; - _My_handler::_M_init_functor(_M_functor, __f); + _My_handler::_M_init_functor(_M_functor, std::move(__f)); } } @@ -2076,13 +2077,7 @@ namespace std operator()(_ArgTypes... __args) const { if (_M_empty()) - { -#if __EXCEPTIONS - throw bad_function_call(); -#else - __builtin_abort(); -#endif - } + __throw_bad_function_call(); return _M_invoker(_M_functor, std::forward<_ArgTypes>(__args)...); } diff --git a/libstdc++-v3/src/functexcept.cc b/libstdc++-v3/src/functexcept.cc index 352a6b70aef..d47eccbe11c 100644 --- a/libstdc++-v3/src/functexcept.cc +++ b/libstdc++-v3/src/functexcept.cc @@ -29,6 +29,7 @@ #include #include #include +#include #ifdef _GLIBCXX_USE_NLS # include @@ -104,6 +105,9 @@ _GLIBCXX_BEGIN_NAMESPACE(std) __throw_future_error(int __i) { throw future_error(future_errc(__i)); } + void + __throw_bad_function_call() + { throw bad_function_call(); } #else void __throw_bad_exception(void) @@ -169,6 +173,10 @@ _GLIBCXX_BEGIN_NAMESPACE(std) __throw_future_error(int) { std::abort(); } + void + __throw_bad_function_call() + { std::abort(); } + #endif //__EXCEPTIONS _GLIBCXX_END_NAMESPACE diff --git a/libstdc++-v3/testsuite/20_util/function/assign/move_target.cc b/libstdc++-v3/testsuite/20_util/function/assign/move_target.cc new file mode 100644 index 00000000000..0a1c189e504 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/function/assign/move_target.cc @@ -0,0 +1,47 @@ +// { dg-options "-std=gnu++0x" } + +// Copyright (C) 2009 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +#include + +struct moveable +{ + moveable() = default; + ~moveable() = default; + // target object must be CopyConstructible, + // but should not be copied during this test + moveable(const moveable& c) { throw "copied"; } + moveable& operator=(const moveable&) = delete; + moveable(moveable&&) { } + + void operator()() const { } +}; + +void test01() +{ + std::function f; + f = moveable(); + f(); +} + +int main() +{ + test01(); + + return 0; +} diff --git a/libstdc++-v3/testsuite/20_util/function/cons/move_target.cc b/libstdc++-v3/testsuite/20_util/function/cons/move_target.cc new file mode 100644 index 00000000000..2396ca10171 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/function/cons/move_target.cc @@ -0,0 +1,46 @@ +// { dg-options "-std=gnu++0x" } + +// Copyright (C) 2009 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +#include + +struct moveable +{ + moveable() = default; + ~moveable() = default; + // target object must be CopyConstructible, + // but should not be copied during this test + moveable(const moveable& c) { throw "copied"; } + moveable& operator=(const moveable&) = delete; + moveable(moveable&&) { } + + void operator()() const { } +}; + +void test01() +{ + std::function f = moveable(); + f(); +} + +int main() +{ + test01(); + + return 0; +}