+2017-01-12 Jonathan Wakely <jwakely@redhat.com>
+
+ 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 <jwakely@redhat.com>
PR libstdc++/78134
</em></span>
</span></dt><dd><p>Safely detect <code class="code">tuple_size<T>::value</code> and
only use it if valid.
+ </p></dd><dt><span class="term"><a class="link" href="../ext/lwg-defects.html#2781" target="_top">2781</a>:
+ <span class="emphasis"><em>Contradictory requirements for <code class="code">std::function</code>
+ and <code class="code">std::reference_wrapper</code>
+ </em></span>
+ </span></dt><dd><p>Remove special handling for <code class="code">reference_wrapper</code>
+ arguments and store them directly as the target object.
</p></dd></dl></div></div></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="license.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="status.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="setup.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">License </td><td width="20%" align="center"><a accesskey="h" href="../index.html">Home</a></td><td width="40%" align="right" valign="top"> Chapter 2. Setup</td></tr></table></div></body></html>
\ No newline at end of file
For Texinfo output, something that transforms valid Docbook
XML to Texinfo is required. The default choice is <a class="link" href="http://docbook2x.sourceforge.net/" target="_top">docbook2X</a>.
</p><p>
- For epub output, the <a class="link" href="http://sourceforge.net/projects/docbook/files/epub3/" target="_top">stylesheets</a> for EPUB3 are required. These stylesheets are still in development. To validate the created file, <a class="link" href="https://code.google.com/p/epubcheck/" target="_top">epubcheck</a> is necessary.
+ For epub output, the <a class="link" href="https://sourceforge.net/projects/docbook/files/epub3/" target="_top">stylesheets</a> for EPUB3 are required. These stylesheets are still in development. To validate the created file, <a class="link" href="https://code.google.com/p/epubcheck/" target="_top">epubcheck</a> is necessary.
</p></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a id="docbook.rules"></a>Generating the DocBook Files</h4></div></div></div><p>
The following Makefile rules generate (in order): an HTML
version of all the DocBook documentation, a PDF version of the
only use it if valid.
</para></listitem></varlistentry>
+ <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="../ext/lwg-defects.html#2781">2781</link>:
+ <emphasis>Contradictory requirements for <code>std::function</code>
+ and <code>std::reference_wrapper</code>
+ </emphasis>
+ </term>
+ <listitem><para>Remove special handling for <code>reference_wrapper</code>
+ arguments and store them directly as the target object.
+ </para></listitem></varlistentry>
+
</variablelist>
</section>
{ __functor._M_access<_Functor*>() = new _Functor(std::move(__f)); }
};
- template<typename _Functor>
- 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<const type_info*>() = &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()
_M_manager(_M_functor, _M_functor, __destroy_functor);
}
-
bool _M_empty() const { return !_M_manager; }
typedef bool (*_Manager_type)(_Any_data&, const _Any_data&,
}
};
- template<typename _Res, typename _Functor, typename... _ArgTypes>
- 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<typename _Functor, typename... _ArgTypes>
- class _Function_handler<void(_ArgTypes...), reference_wrapper<_Functor> >
- : 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<typename _Class, typename _Member, typename _Res,
typename... _ArgTypes>
class _Function_handler<_Res(_ArgTypes...), _Member _Class::*>
* @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<typename _Functor> _Functor* target() noexcept;
- /// @overload
template<typename _Functor> const _Functor* target() const noexcept;
+ // @}
#endif
private:
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<typename _Res, typename... _ArgTypes>
return __ptr._M_access<const _Functor*>();
}
else
- return 0;
+ return nullptr;
}
#endif
#include <functional>
#include <testsuite_hooks.h>
-using namespace __gnu_test;
+template<typename T>
+ const T&
+ as_const(T& t)
+ { return t; }
+
+// Check that f's target is a reference_wrapper bound to obj.
+template<typename Function, typename T>
+ bool
+ wraps(Function& f, T& obj)
+ {
+ using ref_wrapper_type = std::reference_wrapper<T>;
+ auto* p = f.template target<ref_wrapper_type>();
+ return std::addressof(p->get()) == std::addressof(obj);
+ }
struct secret {};
function<int()> f(ref(x));
VERIFY( f );
VERIFY( f() == 17 );
- VERIFY( f.target_type() == typeid(noncopyable_function_object_type) );
- VERIFY( f.target<noncopyable_function_object_type>() == &x );
+ VERIFY( f.target_type() == typeid(std::ref(x)) ); // LWG 2781
+ VERIFY( wraps(f, x) );
function<int()> g = f;
VERIFY( g );
VERIFY( g() == 17 );
- VERIFY( g.target_type() == typeid(noncopyable_function_object_type) );
- VERIFY( g.target<noncopyable_function_object_type>() == &x );
+ VERIFY( g.target_type() == f.target_type() );
+ VERIFY( wraps(g, x) );
function<int()> h = cref(x);
VERIFY( h );
VERIFY( h() == 42 );
- VERIFY( h.target_type() == typeid(noncopyable_function_object_type) );
- VERIFY( h.target<const noncopyable_function_object_type>() == &x );
- VERIFY( h.target<const noncopyable_function_object_type>() == &x );
+ VERIFY( h.target_type() == typeid(std::cref(x)) );
+ VERIFY( wraps(h, as_const(x)) );
const function<int()>& hc = h;
- VERIFY( h.target<noncopyable_function_object_type>() == 0 );
- VERIFY( hc.target<noncopyable_function_object_type>() == &x );
+ VERIFY( hc.target_type() == h.target_type() );
+ VERIFY( wraps(hc, as_const(x)) );
}
int main()
#include <testsuite_hooks.h>
#include <testsuite_tr1.h>
-using namespace __gnu_test;
+template<typename T>
+ const T&
+ as_const(T& t)
+ { return t; }
+
+// Check that f's target is a reference_wrapper bound to obj.
+template<typename Function, typename T>
+ bool
+ wraps(Function& f, T& obj)
+ {
+ using ref_wrapper_type = std::reference_wrapper<T>;
+ auto* p = f.template target<ref_wrapper_type>();
+ return std::addressof(p->get()) == std::addressof(obj);
+ }
// Put reference_wrappers to function pointers into function<> wrappers
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<int(float)> f1(ref(fptr));
VERIFY( f1 );
// target_type and target() functions
const function<int(float)>& f1c = f1;
- VERIFY( typeid(int(*)(float)) == f1.target_type() );
- VERIFY( f1.target<int(*)(float)>() != 0 );
- VERIFY( f1.target<int(*)(float)>() == &fptr );
- VERIFY( f1c.target<int(*)(float)>() != 0 );
- VERIFY( f1c.target<int(*)(float)>() == &fptr );
+ using ref_wrapper_type = reference_wrapper<int(*)(float)>;
+ VERIFY( typeid(ref_wrapper_type) == f1.target_type() );
+ VERIFY( f1.target<ref_wrapper_type>() != nullptr );
+ VERIFY( wraps(f1, fptr) );
+ VERIFY( wraps(f1c, fptr) );
function<int(float)> f2(cref(fptr));
VERIFY( f2 );
// target_type and target() functions
const function<int(float)>& f2c = f2;
- VERIFY( typeid(int(*)(float)) == f2.target_type() );
- VERIFY( f2.target<int(*)(float)>() == 0 );
- VERIFY( f2.target<int(* const)(float)>() == &fptr );
- VERIFY( f2c.target<int(*)(float)>() != 0 );
- VERIFY( f2c.target<int(*)(float)>() == &fptr );
+ using cref_wrapper_type = reference_wrapper<int(* const)(float)>;
+ 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()
#include <testsuite_hooks.h>
#include <testsuite_tr1.h>
-using namespace __gnu_test;
+template<typename T>
+ const T&
+ as_const(T& t)
+ { return t; }
+
+// Check that f's target is a reference_wrapper bound to obj.
+template<typename Function, typename T>
+ bool
+ wraps(Function& f, T& obj)
+ {
+ using ref_wrapper_type = std::reference_wrapper<T>;
+ auto* p = f.template target<ref_wrapper_type>();
+ return std::addressof(p->get()) == std::addressof(obj);
+ }
// Put reference_wrappers to member pointers
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;
function<int(X&)> frm(ref(X_bar));
VERIFY( frm );
VERIFY( frm(x) == 17 );
- VERIFY( typeid(int X::*) == frm.target_type() );
- VERIFY( frm.target<int X::*>() == &X_bar );
+ VERIFY( typeid(ref(X_bar)) == frm.target_type() );
+ VERIFY( wraps(frm, X_bar) );
function<int(X&)> fr(ref(X_foo));
VERIFY( fr );
VERIFY( fr(x) == 1 );
- VERIFY( typeid(int (X::*)()) == fr.target_type() );
- VERIFY( fr.target<int (X::*)()>() == &X_foo );
+ VERIFY( typeid(ref(X_foo)) == fr.target_type() );
+ VERIFY( wraps(fr, X_foo) );
function<int(const X&)> frc(ref(X_foo_c));
VERIFY( frc );
VERIFY( frc(x) == 2 );
- VERIFY( typeid(int (X::*)() const) == frc.target_type() );
- VERIFY( frc.target<int (X::*)() const >() == &X_foo_c );
+ VERIFY( typeid(ref(X_foo_c)) == frc.target_type() );
+ VERIFY( wraps(frc, X_foo_c) );
function<int(volatile X&)> frv(ref(X_foo_v));
VERIFY( frv );
VERIFY( frv(x) == 3 );
- VERIFY( typeid(int (X::*)() volatile) == frv.target_type() );
- VERIFY( *frv.target<int (X::*)() volatile >() == X_foo_v );
- VERIFY( frv.target<int (X::*)() const volatile>() == 0 );
+ VERIFY( typeid(ref(X_foo_v)) == frv.target_type() );
+ VERIFY( wraps(frv, X_foo_v) );
function<int(const volatile X&)> frcv(ref(X_foo_cv));
VERIFY( frcv );
VERIFY( frcv(x) == 4 );
- VERIFY( typeid(int (X::*)() const volatile) == frcv.target_type() );
- VERIFY( *frcv.target<int (X::*)() const volatile >() == X_foo_cv );
- VERIFY( frcv.target<int (X::*)() const>() == 0 );
+ VERIFY( typeid(ref(X_foo_cv)) == frcv.target_type() );
+ VERIFY( wraps(frcv, X_foo_cv) );
function<int(X*)> grm(ref(X_bar));
VERIFY( grm );
VERIFY( grm(&x) == 17 );
- VERIFY( typeid(int X::*) == grm.target_type() );
- VERIFY( *grm.target<int X::*>() == X_bar );
+ VERIFY( typeid(ref(X_bar)) == grm.target_type() );
+ VERIFY( wraps(grm, X_bar) );
function<int(X*)> gr(ref(X_foo));
VERIFY( gr );
VERIFY( gr(&x) == 1 );
- VERIFY( typeid(int (X::*)()) == gr.target_type() );
- VERIFY( *gr.target<int (X::*)()>() == X_foo );
+ VERIFY( typeid(ref(X_foo)) == gr.target_type() );
+ VERIFY( wraps(gr, X_foo) );
function<int(const X*)> grc(ref(X_foo_c));
VERIFY( grc );
VERIFY( grc(&x) == 2 );
- VERIFY( typeid(int (X::*)() const) == grc.target_type() );
- VERIFY( *grc.target<int (X::*)() const >() == X_foo_c );
+ VERIFY( typeid(ref(X_foo_c)) == grc.target_type() );
+ VERIFY( wraps(grc, X_foo_c) );
function<int(volatile X*)> grv(ref(X_foo_v));
VERIFY( grv );
VERIFY( grv(&x) == 3 );
- VERIFY( typeid(int (X::*)() volatile) == grv.target_type() );
- VERIFY( *grv.target<int (X::*)() volatile >() == X_foo_v );
- VERIFY( grv.target<int (X::*)() const volatile>() == 0 );
+ VERIFY( typeid(ref(X_foo_v)) == grv.target_type() );
+ VERIFY( wraps(grv, X_foo_v) );
function<int(const volatile X*)> grcv(ref(X_foo_cv));
VERIFY( grcv );
VERIFY( grcv(&x) == 4 );
- VERIFY( typeid(int (X::*)() const volatile) == grcv.target_type() );
- VERIFY( *grcv.target<int (X::*)() const volatile >() == X_foo_cv );
- VERIFY( grcv.target<int (X::*)() const>() == 0 );
+ VERIFY( typeid(ref(X_foo_cv)) == grcv.target_type() );
+ VERIFY( wraps(grcv, X_foo_cv) );
function<int(X&)> hrm(cref(X_bar));
VERIFY( hrm );
VERIFY( hrm(x) == 17 );
- VERIFY( typeid(int X::*) == hrm.target_type() );
- VERIFY( hrm.target<int X::*>() == 0 );
- VERIFY( hrm.target<int X::* const>() == &X_bar );
+ VERIFY( typeid(cref(X_bar)) == hrm.target_type() );
+ VERIFY( wraps(hrm, as_const(X_bar)) );
function<int(X&)> hr(cref(X_foo));
VERIFY( hr );
VERIFY( hr(x) == 1 );
- VERIFY( typeid(int (X::*)()) == hr.target_type() );
- VERIFY( hr.target<int (X::* const)()>() == &X_foo );
+ VERIFY( typeid(cref(X_foo)) == hr.target_type() );
+ VERIFY( wraps(hr, as_const(X_foo)) );
function<int(const X&)> hrc(cref(X_foo_c));
VERIFY( hrc );
VERIFY( hrc(x) == 2 );
- VERIFY( typeid(int (X::*)() const) == hrc.target_type() );
- VERIFY( hrc.target<int (X::* const)() const >() == &X_foo_c );
+ VERIFY( typeid(cref(X_foo_c)) == hrc.target_type() );
+ VERIFY( wraps(hrc, as_const(X_foo_c)) );
function<int(volatile X&)> hrv(cref(X_foo_v));
VERIFY( hrv );
VERIFY( hrv(x) == 3 );
- VERIFY( typeid(int (X::*)() volatile) == hrv.target_type() );
- VERIFY( hrv.target<int (X::* const)() volatile >() == &X_foo_v );
- VERIFY( hrv.target<int (X::* const)() const volatile>() == 0 );
+ VERIFY( typeid(cref(X_foo_v)) == hrv.target_type() );
+ VERIFY( wraps(hrv, as_const(X_foo_v)) );
function<int(const volatile X&)> hrcv(cref(X_foo_cv));
VERIFY( hrcv );
VERIFY( hrcv(x) == 4 );
- VERIFY( typeid(int (X::*)() const volatile) == hrcv.target_type() );
- VERIFY( hrcv.target<int (X::* const)() const volatile >() == &X_foo_cv );
- VERIFY( hrcv.target<int (X::* const)() const>() == 0 );
+ VERIFY( typeid(cref(X_foo_cv)) == hrcv.target_type() );
+ VERIFY( wraps(hrcv, as_const(X_foo_cv)) );
}
int main()