From ffc500dd41fd49db8e5ec5022389b664a1a04e6d Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Tue, 6 Aug 2019 16:57:55 +0100 Subject: [PATCH] P1651R0 bind_front should not unwrap reference_wrapper P1651R0 bind_front should not unwrap reference_wrapper * include/std/functional (bind_front): Don't unwrap reference_wrapper. * include/std/version (__cpp_lib_bind_front): Update value. * testsuite/20_util/function_objects/bind_front/1.cc: Fix test for feature test macro. * testsuite/20_util/function_objects/bind_front/2.cc: New test. From-SVN: r274146 --- libstdc++-v3/ChangeLog | 7 ++ libstdc++-v3/include/std/functional | 4 +- libstdc++-v3/include/std/version | 2 +- .../20_util/function_objects/bind_front/1.cc | 2 +- .../20_util/function_objects/bind_front/2.cc | 91 ++++++++++++++++++++++ 5 files changed, 102 insertions(+), 4 deletions(-) create mode 100644 libstdc++-v3/testsuite/20_util/function_objects/bind_front/2.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 7173b90..c8b9326 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,12 @@ 2019-08-06 Jonathan Wakely + P1651R0 bind_front should not unwrap reference_wrapper + * include/std/functional (bind_front): Don't unwrap reference_wrapper. + * include/std/version (__cpp_lib_bind_front): Update value. + * testsuite/20_util/function_objects/bind_front/1.cc: Fix test for + feature test macro. + * testsuite/20_util/function_objects/bind_front/2.cc: New test. + * include/std/numbers [!__STRICT_ANSI__ && _GLIBCXX_USE_FLOAT128] (e_v, log2e_v, log10e_v, pi_v, inv_pi_v, inv_sqrtpi_v, ln2_v, ln10_v) (sqrt2_v, sqrt3_v, inv_sqrt3, egamma_v, phi_v): Add explicit diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional index d610e91..30576f2 100644 --- a/libstdc++-v3/include/std/functional +++ b/libstdc++-v3/include/std/functional @@ -791,7 +791,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } #if __cplusplus > 201703L -#define __cpp_lib_bind_front 201902L +#define __cpp_lib_bind_front 201907L template struct _Bind_front @@ -877,7 +877,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template using _Bind_front_t - = _Bind_front, unwrap_ref_decay_t<_Args>...>; + = _Bind_front, decay_t<_Args>...>; template _Bind_front_t<_Fn, _Args...> diff --git a/libstdc++-v3/include/std/version b/libstdc++-v3/include/std/version index bf15a0e..9548725 100644 --- a/libstdc++-v3/include/std/version +++ b/libstdc++-v3/include/std/version @@ -151,7 +151,7 @@ #if __cplusplus > 201703L // c++2a #define __cpp_lib_atomic_ref 201806L -#define __cpp_lib_bind_front 201902L +#define __cpp_lib_bind_front 201907L #define __cpp_lib_bounded_array_traits 201902L #if __cpp_impl_destroying_delete # define __cpp_lib_destroying_delete 201806L diff --git a/libstdc++-v3/testsuite/20_util/function_objects/bind_front/1.cc b/libstdc++-v3/testsuite/20_util/function_objects/bind_front/1.cc index 8ebc2ba..c6cf5cf 100644 --- a/libstdc++-v3/testsuite/20_util/function_objects/bind_front/1.cc +++ b/libstdc++-v3/testsuite/20_util/function_objects/bind_front/1.cc @@ -23,7 +23,7 @@ #ifndef __cpp_lib_bind_front # error "Feature test macro for bind_front is missing" -#elif __cpp_lib_bind_front < 201811L +#elif __cpp_lib_bind_front < 201902L # error "Feature test macro for bind_front has wrong value" #endif diff --git a/libstdc++-v3/testsuite/20_util/function_objects/bind_front/2.cc b/libstdc++-v3/testsuite/20_util/function_objects/bind_front/2.cc new file mode 100644 index 0000000..b68cc65 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/function_objects/bind_front/2.cc @@ -0,0 +1,91 @@ +// Copyright (C) 2019 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 +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include +#include + +// P1651R0 bind_front should not unwrap reference_wrapper + +#ifndef __cpp_lib_bind_front +# error "Feature test macro for bind_front is missing" +#elif __cpp_lib_bind_front < 201907L +# error "Feature test macro for bind_front has wrong value" +#endif + +void functionAcceptingStringView(std::string_view) { } + +void +test01() +{ + std::string s; + auto fs = std::bind_front(&functionAcceptingStringView, std::string_view(s)); + fs(); +} + +template +struct PartialApply { + PartialApply(F f) : f(f) {} + F f; + + template decltype(auto) operator()(A const&... a) const { + if constexpr (std::is_invocable::value) { + return f(a...); + } else { + return bind_front(*this, a...); + } + } +}; + +void +test02() +{ + struct Thingy { }; + std::unique_ptr thingy; + auto func = [](const std::unique_ptr&, int) {}; + PartialApply{func}(std::ref(thingy))(10); +} + +void +test03() +{ + std::string str; + auto func = [](const std::string& s, int) -> const std::string& { return s; }; + + // sref refers to copy of str stored in bind_front result: + const std::string& sref = PartialApply{func}(std::ref(str))(10); + + // pre-P1651R0 this is a use of a dangling reference: + const char& c = sref[0]; + + // post-P1651R0 the bind_front result stores a reference_wrapper by value, + // and so sref is bound to str instead of dangling: + VERIFY( &c == str.data() ); + VERIFY( &sref == &str ); +} + +int +main() +{ + test01(); + test02(); + test03(); +} -- 2.7.4