From 4704f28e7a59c82fab92109ac6f22e3b14a0344b Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Thu, 12 Jan 2017 14:28:38 +0000 Subject: [PATCH] PR66284 remove std::function special case for reference_wrapper PR libstdc++/66284 * doc/xml/manual/intro.xml: Document LWG 2781 change. * doc/html/*: Regenerate. * include/std/functional (_Function_base::_Ref_manager): Remove. (_Function_handler): Remove partial specializations for reference_wrapper. (function::target): Remove special case for const qualification. * testsuite/20_util/function/6.cc: Adjust tests for target type. * testsuite/20_util/function/7.cc: Likewise. * testsuite/20_util/function/8.cc: Likewise. From-SVN: r244364 --- libstdc++-v3/ChangeLog | 13 +++ libstdc++-v3/doc/html/manual/bugs.html | 6 ++ .../html/manual/documentation_hacking.html | 2 +- libstdc++-v3/doc/xml/manual/intro.xml | 9 ++ libstdc++-v3/include/bits/std_function.h | 90 ++----------------- libstdc++-v3/testsuite/20_util/function/6.cc | 32 ++++--- libstdc++-v3/testsuite/20_util/function/7.cc | 38 +++++--- libstdc++-v3/testsuite/20_util/function/8.cc | 84 +++++++++-------- 8 files changed, 132 insertions(+), 142 deletions(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 35fbb95f617..7a70e250bf7 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,16 @@ +2017-01-12 Jonathan Wakely + + PR libstdc++/66284 + * doc/xml/manual/intro.xml: Document LWG 2781 change. + * doc/html/*: Regenerate. + * include/std/functional (_Function_base::_Ref_manager): Remove. + (_Function_handler): Remove partial specializations for + reference_wrapper. + (function::target): Remove special case for const qualification. + * testsuite/20_util/function/6.cc: Adjust tests for target type. + * testsuite/20_util/function/7.cc: Likewise. + * testsuite/20_util/function/8.cc: Likewise. + 2017-01-11 Jonathan Wakely PR libstdc++/78134 diff --git a/libstdc++-v3/doc/html/manual/bugs.html b/libstdc++-v3/doc/html/manual/bugs.html index ee39a954c5c..439df7dc6fe 100644 --- a/libstdc++-v3/doc/html/manual/bugs.html +++ b/libstdc++-v3/doc/html/manual/bugs.html @@ -509,4 +509,10 @@

Safely detect tuple_size<T>::value and only use it if valid. +

2781: + Contradictory requirements for std::function + and std::reference_wrapper + +

Remove special handling for reference_wrapper + arguments and store them directly as the target object.

\ No newline at end of file diff --git a/libstdc++-v3/doc/html/manual/documentation_hacking.html b/libstdc++-v3/doc/html/manual/documentation_hacking.html index 26d8a6fba03..7325cbee444 100644 --- a/libstdc++-v3/doc/html/manual/documentation_hacking.html +++ b/libstdc++-v3/doc/html/manual/documentation_hacking.html @@ -368,7 +368,7 @@ For Texinfo output, something that transforms valid Docbook XML to Texinfo is required. The default choice is docbook2X.

- For epub output, the stylesheets for EPUB3 are required. These stylesheets are still in development. To validate the created file, epubcheck is necessary. + For epub output, the stylesheets for EPUB3 are required. These stylesheets are still in development. To validate the created file, epubcheck is necessary.

Generating the DocBook Files

The following Makefile rules generate (in order): an HTML version of all the DocBook documentation, a PDF version of the diff --git a/libstdc++-v3/doc/xml/manual/intro.xml b/libstdc++-v3/doc/xml/manual/intro.xml index d23008ad332..db6e09a7793 100644 --- a/libstdc++-v3/doc/xml/manual/intro.xml +++ b/libstdc++-v3/doc/xml/manual/intro.xml @@ -1116,6 +1116,15 @@ requirements of the license of GCC. only use it if valid. + 2781: + Contradictory requirements for std::function + and std::reference_wrapper + + + Remove special handling for reference_wrapper + arguments and store them directly as the target object. + + diff --git a/libstdc++-v3/include/bits/std_function.h b/libstdc++-v3/include/bits/std_function.h index f7bb22a313e..7d77e213b50 100644 --- a/libstdc++-v3/include/bits/std_function.h +++ b/libstdc++-v3/include/bits/std_function.h @@ -268,41 +268,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { __functor._M_access<_Functor*>() = new _Functor(std::move(__f)); } }; - template - class _Ref_manager : public _Base_manager<_Functor*> - { - typedef _Function_base::_Base_manager<_Functor*> _Base; - - public: - static bool - _M_manager(_Any_data& __dest, const _Any_data& __source, - _Manager_operation __op) - { - switch (__op) - { -#if __cpp_rtti - case __get_type_info: - __dest._M_access() = &typeid(_Functor); - break; -#endif - case __get_functor_ptr: - __dest._M_access<_Functor*>() = *_Base::_M_get_pointer(__source); - return is_const<_Functor>::value; - break; - - default: - _Base::_M_manager(__dest, __source, __op); - } - return false; - } - - static void - _M_init_functor(_Any_data& __functor, reference_wrapper<_Functor> __f) - { - _Base::_M_init_functor(__functor, std::__addressof(__f.get())); - } - }; - _Function_base() : _M_manager(nullptr) { } ~_Function_base() @@ -311,7 +276,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_manager(_M_functor, _M_functor, __destroy_functor); } - bool _M_empty() const { return !_M_manager; } typedef bool (*_Manager_type)(_Any_data&, const _Any_data&, @@ -354,36 +318,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } }; - template - class _Function_handler<_Res(_ArgTypes...), reference_wrapper<_Functor> > - : public _Function_base::_Ref_manager<_Functor> - { - typedef _Function_base::_Ref_manager<_Functor> _Base; - - public: - static _Res - _M_invoke(const _Any_data& __functor, _ArgTypes&&... __args) - { - return std::__invoke(**_Base::_M_get_pointer(__functor), - std::forward<_ArgTypes>(__args)...); - } - }; - - template - class _Function_handler > - : public _Function_base::_Ref_manager<_Functor> - { - typedef _Function_base::_Ref_manager<_Functor> _Base; - - public: - static void - _M_invoke(const _Any_data& __functor, _ArgTypes&&... __args) - { - std::__invoke(**_Base::_M_get_pointer(__functor), - std::forward<_ArgTypes>(__args)...); - } - }; - template class _Function_handler<_Res(_ArgTypes...), _Member _Class::*> @@ -677,15 +611,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @brief Access the stored target function object. * * @return Returns a pointer to the stored target function object, - * if @c typeid(Functor).equals(target_type()); otherwise, a NULL + * if @c typeid(_Functor).equals(target_type()); otherwise, a NULL * pointer. * - * This function will not throw an %exception. + * This function does not throw exceptions. + * + * @{ */ template _Functor* target() noexcept; - /// @overload template const _Functor* target() const noexcept; + // @} #endif private: @@ -755,17 +691,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION function<_Res(_ArgTypes...)>:: target() noexcept { - if (typeid(_Functor) == target_type() && _M_manager) - { - _Any_data __ptr; - if (_M_manager(__ptr, _M_functor, __get_functor_ptr) - && !is_const<_Functor>::value) - return 0; - else - return __ptr._M_access<_Functor*>(); - } - else - return 0; + const function* __const_this = this; + const _Functor* __func = __const_this->template target<_Functor>(); + return const_cast<_Functor*>(__func); } template @@ -781,7 +709,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __ptr._M_access(); } else - return 0; + return nullptr; } #endif diff --git a/libstdc++-v3/testsuite/20_util/function/6.cc b/libstdc++-v3/testsuite/20_util/function/6.cc index 94c123434be..c224ec5412d 100644 --- a/libstdc++-v3/testsuite/20_util/function/6.cc +++ b/libstdc++-v3/testsuite/20_util/function/6.cc @@ -22,7 +22,20 @@ #include #include -using namespace __gnu_test; +template + const T& + as_const(T& t) + { return t; } + +// Check that f's target is a reference_wrapper bound to obj. +template + bool + wraps(Function& f, T& obj) + { + using ref_wrapper_type = std::reference_wrapper; + auto* p = f.template target(); + return std::addressof(p->get()) == std::addressof(obj); + } struct secret {}; @@ -52,25 +65,24 @@ void test06() function f(ref(x)); VERIFY( f ); VERIFY( f() == 17 ); - VERIFY( f.target_type() == typeid(noncopyable_function_object_type) ); - VERIFY( f.target() == &x ); + VERIFY( f.target_type() == typeid(std::ref(x)) ); // LWG 2781 + VERIFY( wraps(f, x) ); function g = f; VERIFY( g ); VERIFY( g() == 17 ); - VERIFY( g.target_type() == typeid(noncopyable_function_object_type) ); - VERIFY( g.target() == &x ); + VERIFY( g.target_type() == f.target_type() ); + VERIFY( wraps(g, x) ); function h = cref(x); VERIFY( h ); VERIFY( h() == 42 ); - VERIFY( h.target_type() == typeid(noncopyable_function_object_type) ); - VERIFY( h.target() == &x ); - VERIFY( h.target() == &x ); + VERIFY( h.target_type() == typeid(std::cref(x)) ); + VERIFY( wraps(h, as_const(x)) ); const function& hc = h; - VERIFY( h.target() == 0 ); - VERIFY( hc.target() == &x ); + VERIFY( hc.target_type() == h.target_type() ); + VERIFY( wraps(hc, as_const(x)) ); } int main() diff --git a/libstdc++-v3/testsuite/20_util/function/7.cc b/libstdc++-v3/testsuite/20_util/function/7.cc index 28337f4efd1..b10ecb8a161 100644 --- a/libstdc++-v3/testsuite/20_util/function/7.cc +++ b/libstdc++-v3/testsuite/20_util/function/7.cc @@ -23,7 +23,20 @@ #include #include -using namespace __gnu_test; +template + const T& + as_const(T& t) + { return t; } + +// Check that f's target is a reference_wrapper bound to obj. +template + bool + wraps(Function& f, T& obj) + { + using ref_wrapper_type = std::reference_wrapper; + auto* p = f.template target(); + return std::addressof(p->get()) == std::addressof(obj); + } // Put reference_wrappers to function pointers into function<> wrappers void test07() @@ -31,8 +44,9 @@ void test07() using std::function; using std::ref; using std::cref; + using std::reference_wrapper; - int (*fptr)(float) = truncate_float; + int (*fptr)(float) = __gnu_test::truncate_float; function f1(ref(fptr)); VERIFY( f1 ); @@ -47,11 +61,11 @@ void test07() // target_type and target() functions const function& f1c = f1; - VERIFY( typeid(int(*)(float)) == f1.target_type() ); - VERIFY( f1.target() != 0 ); - VERIFY( f1.target() == &fptr ); - VERIFY( f1c.target() != 0 ); - VERIFY( f1c.target() == &fptr ); + using ref_wrapper_type = reference_wrapper; + VERIFY( typeid(ref_wrapper_type) == f1.target_type() ); + VERIFY( f1.target() != nullptr ); + VERIFY( wraps(f1, fptr) ); + VERIFY( wraps(f1c, fptr) ); function f2(cref(fptr)); VERIFY( f2 ); @@ -66,11 +80,11 @@ void test07() // target_type and target() functions const function& f2c = f2; - VERIFY( typeid(int(*)(float)) == f2.target_type() ); - VERIFY( f2.target() == 0 ); - VERIFY( f2.target() == &fptr ); - VERIFY( f2c.target() != 0 ); - VERIFY( f2c.target() == &fptr ); + using cref_wrapper_type = reference_wrapper; + VERIFY( typeid(cref_wrapper_type) == f2.target_type() ); + VERIFY( wraps(f2, as_const(fptr)) ); + VERIFY( f2c.target_type() == f2.target_type() ); + VERIFY( wraps(f2c, as_const(fptr)) ); } int main() diff --git a/libstdc++-v3/testsuite/20_util/function/8.cc b/libstdc++-v3/testsuite/20_util/function/8.cc index 358399450a1..e641057d151 100644 --- a/libstdc++-v3/testsuite/20_util/function/8.cc +++ b/libstdc++-v3/testsuite/20_util/function/8.cc @@ -23,7 +23,20 @@ #include #include -using namespace __gnu_test; +template + const T& + as_const(T& t) + { return t; } + +// Check that f's target is a reference_wrapper bound to obj. +template + bool + wraps(Function& f, T& obj) + { + using ref_wrapper_type = std::reference_wrapper; + auto* p = f.template target(); + return std::addressof(p->get()) == std::addressof(obj); + } // Put reference_wrappers to member pointers void test08() @@ -31,6 +44,8 @@ void test08() using std::function; using std::ref; using std::cref; + using std::reference_wrapper; + using __gnu_test::X; int X::* X_bar = &X::bar; int (X::* X_foo)() = &X::foo; @@ -44,99 +59,92 @@ void test08() function frm(ref(X_bar)); VERIFY( frm ); VERIFY( frm(x) == 17 ); - VERIFY( typeid(int X::*) == frm.target_type() ); - VERIFY( frm.target() == &X_bar ); + VERIFY( typeid(ref(X_bar)) == frm.target_type() ); + VERIFY( wraps(frm, X_bar) ); function fr(ref(X_foo)); VERIFY( fr ); VERIFY( fr(x) == 1 ); - VERIFY( typeid(int (X::*)()) == fr.target_type() ); - VERIFY( fr.target() == &X_foo ); + VERIFY( typeid(ref(X_foo)) == fr.target_type() ); + VERIFY( wraps(fr, X_foo) ); function frc(ref(X_foo_c)); VERIFY( frc ); VERIFY( frc(x) == 2 ); - VERIFY( typeid(int (X::*)() const) == frc.target_type() ); - VERIFY( frc.target() == &X_foo_c ); + VERIFY( typeid(ref(X_foo_c)) == frc.target_type() ); + VERIFY( wraps(frc, X_foo_c) ); function frv(ref(X_foo_v)); VERIFY( frv ); VERIFY( frv(x) == 3 ); - VERIFY( typeid(int (X::*)() volatile) == frv.target_type() ); - VERIFY( *frv.target() == X_foo_v ); - VERIFY( frv.target() == 0 ); + VERIFY( typeid(ref(X_foo_v)) == frv.target_type() ); + VERIFY( wraps(frv, X_foo_v) ); function frcv(ref(X_foo_cv)); VERIFY( frcv ); VERIFY( frcv(x) == 4 ); - VERIFY( typeid(int (X::*)() const volatile) == frcv.target_type() ); - VERIFY( *frcv.target() == X_foo_cv ); - VERIFY( frcv.target() == 0 ); + VERIFY( typeid(ref(X_foo_cv)) == frcv.target_type() ); + VERIFY( wraps(frcv, X_foo_cv) ); function grm(ref(X_bar)); VERIFY( grm ); VERIFY( grm(&x) == 17 ); - VERIFY( typeid(int X::*) == grm.target_type() ); - VERIFY( *grm.target() == X_bar ); + VERIFY( typeid(ref(X_bar)) == grm.target_type() ); + VERIFY( wraps(grm, X_bar) ); function gr(ref(X_foo)); VERIFY( gr ); VERIFY( gr(&x) == 1 ); - VERIFY( typeid(int (X::*)()) == gr.target_type() ); - VERIFY( *gr.target() == X_foo ); + VERIFY( typeid(ref(X_foo)) == gr.target_type() ); + VERIFY( wraps(gr, X_foo) ); function grc(ref(X_foo_c)); VERIFY( grc ); VERIFY( grc(&x) == 2 ); - VERIFY( typeid(int (X::*)() const) == grc.target_type() ); - VERIFY( *grc.target() == X_foo_c ); + VERIFY( typeid(ref(X_foo_c)) == grc.target_type() ); + VERIFY( wraps(grc, X_foo_c) ); function grv(ref(X_foo_v)); VERIFY( grv ); VERIFY( grv(&x) == 3 ); - VERIFY( typeid(int (X::*)() volatile) == grv.target_type() ); - VERIFY( *grv.target() == X_foo_v ); - VERIFY( grv.target() == 0 ); + VERIFY( typeid(ref(X_foo_v)) == grv.target_type() ); + VERIFY( wraps(grv, X_foo_v) ); function grcv(ref(X_foo_cv)); VERIFY( grcv ); VERIFY( grcv(&x) == 4 ); - VERIFY( typeid(int (X::*)() const volatile) == grcv.target_type() ); - VERIFY( *grcv.target() == X_foo_cv ); - VERIFY( grcv.target() == 0 ); + VERIFY( typeid(ref(X_foo_cv)) == grcv.target_type() ); + VERIFY( wraps(grcv, X_foo_cv) ); function hrm(cref(X_bar)); VERIFY( hrm ); VERIFY( hrm(x) == 17 ); - VERIFY( typeid(int X::*) == hrm.target_type() ); - VERIFY( hrm.target() == 0 ); - VERIFY( hrm.target() == &X_bar ); + VERIFY( typeid(cref(X_bar)) == hrm.target_type() ); + VERIFY( wraps(hrm, as_const(X_bar)) ); function hr(cref(X_foo)); VERIFY( hr ); VERIFY( hr(x) == 1 ); - VERIFY( typeid(int (X::*)()) == hr.target_type() ); - VERIFY( hr.target() == &X_foo ); + VERIFY( typeid(cref(X_foo)) == hr.target_type() ); + VERIFY( wraps(hr, as_const(X_foo)) ); function hrc(cref(X_foo_c)); VERIFY( hrc ); VERIFY( hrc(x) == 2 ); - VERIFY( typeid(int (X::*)() const) == hrc.target_type() ); - VERIFY( hrc.target() == &X_foo_c ); + VERIFY( typeid(cref(X_foo_c)) == hrc.target_type() ); + VERIFY( wraps(hrc, as_const(X_foo_c)) ); function hrv(cref(X_foo_v)); VERIFY( hrv ); VERIFY( hrv(x) == 3 ); - VERIFY( typeid(int (X::*)() volatile) == hrv.target_type() ); - VERIFY( hrv.target() == &X_foo_v ); - VERIFY( hrv.target() == 0 ); + VERIFY( typeid(cref(X_foo_v)) == hrv.target_type() ); + VERIFY( wraps(hrv, as_const(X_foo_v)) ); function hrcv(cref(X_foo_cv)); VERIFY( hrcv ); VERIFY( hrcv(x) == 4 ); - VERIFY( typeid(int (X::*)() const volatile) == hrcv.target_type() ); - VERIFY( hrcv.target() == &X_foo_cv ); - VERIFY( hrcv.target() == 0 ); + VERIFY( typeid(cref(X_foo_cv)) == hrcv.target_type() ); + VERIFY( wraps(hrcv, as_const(X_foo_cv)) ); } int main() -- 2.30.2