From 3bbe0237a38fde060a87bedc10177a874c2012f6 Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Tue, 15 Sep 2020 12:18:05 -0700 Subject: [PATCH 1/3] Pre-decay template arguments to _Front_binder Fixes #1292. --- stl/inc/functional | 32 ++++++----- tests/std/tests/P0356R5_bind_front/test.cpp | 61 +++++++++++++++++++++ 2 files changed, 78 insertions(+), 15 deletions(-) diff --git a/stl/inc/functional b/stl/inc/functional index 05b969b5ef2..417a5b5f3c7 100644 --- a/stl/inc/functional +++ b/stl/inc/functional @@ -1557,24 +1557,17 @@ constexpr auto _Call_front_binder(index_sequence<_Ix...>, _Cv_FD&& _Obj, _Cv_tup template class _Front_binder { // wrap bound callable object and arguments private: - static_assert(is_constructible_v, _Fx>, - "std::bind_front() requires the decayed callable to be constructible from an undecayed callable"); - static_assert(is_move_constructible_v>, - "std::bind_front() requires the decayed callable to be move constructible"); - static_assert(conjunction_v, _Types>...>, - "std::bind_front() requires the decayed bound arguments to be constructible from undecayed bound arguments"); - static_assert(conjunction_v>...>, - "std::bind_front() requires the decayed bound arguments to be move constructible"); + using _Seq = index_sequence_for<_Types...>; - using _Seq = index_sequence_for<_Types...>; - using _First = decay_t<_Fx>; - using _Second = tuple...>; + _Compressed_pair<_Fx, tuple<_Types...>> _Mypair; - _Compressed_pair<_First, _Second> _Mypair; + _STL_INTERNAL_STATIC_ASSERT(is_same_v<_Fx, decay_t<_Fx>>); + _STL_INTERNAL_STATIC_ASSERT((is_same_v<_Types, decay_t<_Types>> && ...)); public: - constexpr explicit _Front_binder(_Fx&& _Func, _Types&&... _Args) - : _Mypair(_One_then_variadic_args_t{}, _STD forward<_Fx>(_Func), _STD forward<_Types>(_Args)...) {} + template + constexpr explicit _Front_binder(_Fx_Init&& _Func, _Types_Init&&... _Args) + : _Mypair(_One_then_variadic_args_t{}, _STD forward<_Fx_Init>(_Func), _STD forward<_Types_Init>(_Args)...) {} template constexpr auto operator()(_Unbound&&... _Unbargs) & noexcept(noexcept( @@ -1614,7 +1607,16 @@ public: // FUNCTION TEMPLATE bind_front template _NODISCARD constexpr auto bind_front(_Fx&& _Func, _Types&&... _Args) { - return _Front_binder<_Fx, _Types...>(_STD forward<_Fx>(_Func), _STD forward<_Types>(_Args)...); + static_assert(is_constructible_v, _Fx>, + "std::bind_front requires the decayed callable to be constructible from an undecayed callable"); + static_assert(is_move_constructible_v>, + "std::bind_front requires the decayed callable to be move constructible"); + static_assert(conjunction_v, _Types>...>, + "std::bind_front requires the decayed bound arguments to be constructible from undecayed bound arguments"); + static_assert(conjunction_v>...>, + "std::bind_front requires the decayed bound arguments to be move constructible"); + + return _Front_binder, decay_t<_Types>...>(_STD forward<_Fx>(_Func), _STD forward<_Types>(_Args)...); } #endif // _HAS_CXX20 diff --git a/tests/std/tests/P0356R5_bind_front/test.cpp b/tests/std/tests/P0356R5_bind_front/test.cpp index 804997e3b42..9ec5a4d686b 100644 --- a/tests/std/tests/P0356R5_bind_front/test.cpp +++ b/tests/std/tests/P0356R5_bind_front/test.cpp @@ -164,4 +164,65 @@ int main() { auto bound7 = move(bound6); assert(*move(bound6)() == -9000); assert(*move(bound7)() == 1234); + + // Also test GH-1292 "bind_front violates [func.require]p8" in which the return type of bind_front inadvertently + // depends on the value category and/or cv-qualification if its arguments. + { + struct S { + int i = 42; + }; + S s; + auto lambda = [](S x) { return x.i; }; + auto returns_lambda = [=] { return lambda; }; + auto returns_const_lambda = [=]() -> const decltype(lambda) { return lambda; }; + auto returns_const_S = []() -> const S { return {}; }; + + using T = decltype(bind_front(lambda, s)); + static_assert(is_same_v); + static_assert(is_same_v); + + static_assert(is_same_v); + static_assert(is_same_v); + static_assert(is_same_v); + + static_assert(is_same_v); + static_assert(is_same_v); + static_assert(is_same_v); + + static_assert(is_same_v); + static_assert(is_same_v); + static_assert(is_same_v); + + static_assert(is_same_v); + static_assert(is_same_v); + static_assert(is_same_v); + + static_assert(is_same_v); + static_assert(is_same_v); + static_assert(is_same_v); + + static_assert(is_same_v); + static_assert(is_same_v); + static_assert(is_same_v); + + static_assert(is_same_v); + static_assert(is_same_v); + static_assert(is_same_v); + + static_assert(is_same_v); + static_assert(is_same_v); + static_assert(is_same_v); + + static_assert(is_same_v); + static_assert(is_same_v); + static_assert(is_same_v); + + static_assert(is_same_v); + static_assert(is_same_v); + static_assert(is_same_v); + + static_assert(is_same_v); + static_assert(is_same_v); + static_assert(is_same_v); + } } From 659d2137e3a51c6867306d5a72fdc5aa1c7d7ec3 Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Wed, 16 Sep 2020 21:02:07 -0700 Subject: [PATCH 2/3] Review comments --- stl/inc/functional | 7 ++-- tests/std/tests/P0356R5_bind_front/test.cpp | 42 ++++++++++----------- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/stl/inc/functional b/stl/inc/functional index 417a5b5f3c7..c17d09af039 100644 --- a/stl/inc/functional +++ b/stl/inc/functional @@ -1565,9 +1565,10 @@ private: _STL_INTERNAL_STATIC_ASSERT((is_same_v<_Types, decay_t<_Types>> && ...)); public: - template - constexpr explicit _Front_binder(_Fx_Init&& _Func, _Types_Init&&... _Args) - : _Mypair(_One_then_variadic_args_t{}, _STD forward<_Fx_Init>(_Func), _STD forward<_Types_Init>(_Args)...) {} + template , _Front_binder>, int> = 0> + constexpr explicit _Front_binder(_FxInit&& _Func, _TypesInit&&... _Args) + : _Mypair(_One_then_variadic_args_t{}, _STD forward<_FxInit>(_Func), _STD forward<_TypesInit>(_Args)...) {} template constexpr auto operator()(_Unbound&&... _Unbargs) & noexcept(noexcept( diff --git a/tests/std/tests/P0356R5_bind_front/test.cpp b/tests/std/tests/P0356R5_bind_front/test.cpp index 9ec5a4d686b..804c9c3bb6f 100644 --- a/tests/std/tests/P0356R5_bind_front/test.cpp +++ b/tests/std/tests/P0356R5_bind_front/test.cpp @@ -166,7 +166,7 @@ int main() { assert(*move(bound7)() == 1234); // Also test GH-1292 "bind_front violates [func.require]p8" in which the return type of bind_front inadvertently - // depends on the value category and/or cv-qualification if its arguments. + // depends on the value category and/or cv-qualification of its arguments. { struct S { int i = 42; @@ -178,51 +178,51 @@ int main() { auto returns_const_S = []() -> const S { return {}; }; using T = decltype(bind_front(lambda, s)); - static_assert(is_same_v); + static_assert(is_same_v); static_assert(is_same_v); - static_assert(is_same_v); - static_assert(is_same_v); - static_assert(is_same_v); + static_assert(is_same_v); + static_assert(is_same_v); + static_assert(is_same_v); static_assert(is_same_v); - static_assert(is_same_v); + static_assert(is_same_v); static_assert(is_same_v); static_assert(is_same_v); - static_assert(is_same_v); + static_assert(is_same_v); static_assert(is_same_v); - static_assert(is_same_v); - static_assert(is_same_v); - static_assert(is_same_v); + static_assert(is_same_v); + static_assert(is_same_v); + static_assert(is_same_v); static_assert(is_same_v); - static_assert(is_same_v); + static_assert(is_same_v); static_assert(is_same_v); static_assert(is_same_v); - static_assert(is_same_v); + static_assert(is_same_v); static_assert(is_same_v); - static_assert(is_same_v); - static_assert(is_same_v); - static_assert(is_same_v); + static_assert(is_same_v); + static_assert(is_same_v); + static_assert(is_same_v); static_assert(is_same_v); - static_assert(is_same_v); + static_assert(is_same_v); static_assert(is_same_v); static_assert(is_same_v); - static_assert(is_same_v); + static_assert(is_same_v); static_assert(is_same_v); - static_assert(is_same_v); - static_assert(is_same_v); - static_assert(is_same_v); + static_assert(is_same_v); + static_assert(is_same_v); + static_assert(is_same_v); static_assert(is_same_v); - static_assert(is_same_v); + static_assert(is_same_v); static_assert(is_same_v); } } From 4b8521bcb11801bdc95a3b5f20a8f4f0a79565a1 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 17 Sep 2020 16:57:15 -0700 Subject: [PATCH 3/3] Update stl/inc/functional --- stl/inc/functional | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/functional b/stl/inc/functional index c17d09af039..da251c1bd5a 100644 --- a/stl/inc/functional +++ b/stl/inc/functional @@ -1566,7 +1566,7 @@ private: public: template , _Front_binder>, int> = 0> + enable_if_t, _Front_binder>, int> = 0> constexpr explicit _Front_binder(_FxInit&& _Func, _TypesInit&&... _Args) : _Mypair(_One_then_variadic_args_t{}, _STD forward<_FxInit>(_Func), _STD forward<_TypesInit>(_Args)...) {}