This fixes a bug in the _Callable SFINAE constraint of std::function, where it was using an rvalue _Func in the result_of expression, when the target is actually invoked as an lvalue.
I'm also making std::function use std::__invoke() directly, instead of going via __callable_functor() and/or mem_fn(). __callable_functor conditionally calls std::mem_fn, and mem_fn uses std::__invoke anyway, so we might as well just use that directly. I'm also removing the TODO comments about allocators, because I fixed that by removing them from the standard :-) http://wg21.link/p0302r1 * include/std/functional (__callable_functor): Remove. (_Function_handler::_M_invoke): Use __invoke instead of __callable_functor or mem_fn. (function::_Callable): Use lvalue in result_of expression. (function): Remove TODO comments about allocators. * testsuite/20_util/function/cons/refqual.cc: New test. Tested powerpc64-linux, committed to trunk.
commit 259d510ed2d371dab3f38c0f425980c5902c1df6 Author: Jonathan Wakely <jwak...@redhat.com> Date: Thu Aug 4 19:24:49 2016 +0100 Use __invoke in std::function internals * include/std/functional (__callable_functor): Remove. (_Function_handler::_M_invoke): Use __invoke instead of __callable_functor or mem_fn. (function::_Callable): Use lvalue in result_of expression. (function): Remove TODO comments about allocators. * testsuite/20_util/function/cons/refqual.cc: New test. diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional index 843dc83..4ca32c3 100644 --- a/libstdc++-v3/include/std/functional +++ b/libstdc++-v3/include/std/functional @@ -1483,33 +1483,6 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) : __is_location_invariant<_Tp> { }; - // Converts a reference to a function object into a callable - // function object. - template<typename _Functor> - inline _Functor& - __callable_functor(_Functor& __f) - { return __f; } - - template<typename _Member, typename _Class> - inline _Mem_fn<_Member _Class::*> - __callable_functor(_Member _Class::* &__p) - { return std::mem_fn(__p); } - - template<typename _Member, typename _Class> - inline _Mem_fn<_Member _Class::*> - __callable_functor(_Member _Class::* const &__p) - { return std::mem_fn(__p); } - - template<typename _Member, typename _Class> - inline _Mem_fn<_Member _Class::*> - __callable_functor(_Member _Class::* volatile &__p) - { return std::mem_fn(__p); } - - template<typename _Member, typename _Class> - inline _Mem_fn<_Member _Class::*> - __callable_functor(_Member _Class::* const volatile &__p) - { return std::mem_fn(__p); } - template<typename _Signature> class function; @@ -1731,8 +1704,8 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) static _Res _M_invoke(const _Any_data& __functor, _ArgTypes&&... __args) { - return std::__callable_functor(**_Base::_M_get_pointer(__functor))( - std::forward<_ArgTypes>(__args)...); + return std::__invoke(**_Base::_M_get_pointer(__functor), + std::forward<_ArgTypes>(__args)...); } }; @@ -1746,8 +1719,8 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) static void _M_invoke(const _Any_data& __functor, _ArgTypes&&... __args) { - std::__callable_functor(**_Base::_M_get_pointer(__functor))( - std::forward<_ArgTypes>(__args)...); + std::__invoke(**_Base::_M_get_pointer(__functor), + std::forward<_ArgTypes>(__args)...); } }; @@ -1763,8 +1736,8 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) static _Res _M_invoke(const _Any_data& __functor, _ArgTypes&&... __args) { - return std::mem_fn(_Base::_M_get_pointer(__functor)->__value)( - std::forward<_ArgTypes>(__args)...); + return std::__invoke(_Base::_M_get_pointer(__functor)->__value, + std::forward<_ArgTypes>(__args)...); } }; @@ -1803,8 +1776,8 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) static void _M_invoke(const _Any_data& __functor, _ArgTypes&&... __args) { - std::mem_fn(_Base::_M_get_pointer(__functor)->__value)( - std::forward<_ArgTypes>(__args)...); + std::__invoke(_Base::_M_get_pointer(__functor)->__value, + std::forward<_ArgTypes>(__args)...); } }; @@ -1826,7 +1799,7 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) typedef _Res _Signature_type(_ArgTypes...); template<typename _Func, - typename _Res2 = typename result_of<_Func(_ArgTypes...)>::type> + typename _Res2 = typename result_of<_Func&(_ArgTypes...)>::type> struct _Callable : __check_func_return_type<_Res2, _Res> { }; // Used so the return type convertibility checks aren't done when @@ -1878,8 +1851,6 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) __x.swap(*this); } - // TODO: needs allocator_arg_t - /** * @brief Builds a %function that targets a copy of the incoming * function object. @@ -2006,17 +1977,6 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) std::swap(_M_invoker, __x._M_invoker); } - // TODO: needs allocator_arg_t - /* - template<typename _Functor, typename _Alloc> - void - assign(_Functor&& __f, const _Alloc& __a) - { - function(allocator_arg, __a, - std::forward<_Functor>(__f)).swap(*this); - } - */ - // [3.7.2.3] function capacity /** diff --git a/libstdc++-v3/testsuite/20_util/function/cons/refqual.cc b/libstdc++-v3/testsuite/20_util/function/cons/refqual.cc new file mode 100644 index 0000000..2370579 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/function/cons/refqual.cc @@ -0,0 +1,31 @@ +// Copyright (C) 2016 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 +// <http://www.gnu.org/licenses/>. + +// { dg-do compile { target c++11 } } + +#include <functional> + +struct F { + void operator()() && { } + int operator()() & { return 0; } +}; + +int main() { + F f; + std::function<int()> ff{f}; + return ff(); +}