Index: libcxx/include/__functional/bind.h =================================================================== --- libcxx/include/__functional/bind.h +++ libcxx/include/__functional/bind.h @@ -99,7 +99,7 @@ inline _LIBCPP_INLINE_VISIBILITY typename __enable_if_t < - is_bind_expression<_Ti>::value, + is_bind_expression<__uncvref_t<_Ti>>::value, __invoke_of<_Ti&, _Uj...> >::type __mu(_Ti& __ti, tuple<_Uj...>& __uj) @@ -114,19 +114,19 @@ template struct __mu_return2 { - typedef typename tuple_element::value - 1, _Uj>::type type; + typedef typename tuple_element>::value - 1, _Uj>::type type; }; template inline _LIBCPP_INLINE_VISIBILITY typename enable_if < - 0 < is_placeholder<_Ti>::value, - typename __mu_return2<0 < is_placeholder<_Ti>::value, _Ti, _Uj>::type + 0 < is_placeholder<__uncvref_t<_Ti>>::value, + typename __mu_return2<0 < is_placeholder<__uncvref_t<_Ti>>::value, _Ti, _Uj>::type >::type __mu(_Ti&, _Uj& __uj) { - const size_t _Indx = is_placeholder<_Ti>::value - 1; + const size_t _Indx = is_placeholder<__uncvref_t<_Ti>>::value - 1; return _VSTD::forward::type>(_VSTD::get<_Indx>(__uj)); } @@ -134,8 +134,8 @@ inline _LIBCPP_INLINE_VISIBILITY typename enable_if < - !is_bind_expression<_Ti>::value && - is_placeholder<_Ti>::value == 0 && + !is_bind_expression<__uncvref_t<_Ti>>::value && + is_placeholder<__uncvref_t<_Ti>>::value == 0 && !__is_reference_wrapper<_Ti>::value, _Ti& >::type @@ -169,7 +169,7 @@ template struct __mu_return_impl<_Ti, false, false, true, _TupleUj> { - typedef typename tuple_element::value - 1, + typedef typename tuple_element>::value - 1, _TupleUj>::type&& type; }; @@ -189,9 +189,9 @@ struct __mu_return : public __mu_return_impl<_Ti, __is_reference_wrapper<_Ti>::value, - is_bind_expression<_Ti>::value, - 0 < is_placeholder<_Ti>::value && - is_placeholder<_Ti>::value <= tuple_size<_TupleUj>::value, + is_bind_expression<__uncvref_t<_Ti>>::value, + 0 < is_placeholder<__uncvref_t<_Ti>>::value && + is_placeholder<__uncvref_t<_Ti>>::value <= tuple_size<_TupleUj>::value, _TupleUj> { }; Index: libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.isbind/is_bind_expression.pass.cpp =================================================================== --- libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.isbind/is_bind_expression.pass.cpp +++ libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.isbind/is_bind_expression.pass.cpp @@ -20,8 +20,15 @@ test(const T&) { static_assert(std::is_bind_expression::value == Expected, ""); + LIBCPP_STATIC_ASSERT(std::is_bind_expression::value == Expected, ""); + LIBCPP_STATIC_ASSERT(std::is_bind_expression::value == Expected, ""); + LIBCPP_STATIC_ASSERT(std::is_bind_expression::value == Expected, ""); + #if TEST_STD_VER > 14 static_assert(std::is_bind_expression_v == Expected, ""); + LIBCPP_STATIC_ASSERT(std::is_bind_expression_v == Expected, ""); + LIBCPP_STATIC_ASSERT(std::is_bind_expression_v == Expected, ""); + LIBCPP_STATIC_ASSERT(std::is_bind_expression_v == Expected, ""); #endif } Index: libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.isbind/specialization.pass.cpp =================================================================== --- /dev/null +++ libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.isbind/specialization.pass.cpp @@ -0,0 +1,56 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11 + +// + +// template struct is_bind_expression; +// A program may specialize this template for a program-defined type T +// to have a base characteristic of true_type to indicate that T should +// be treated as a subexpression in a bind call. +// https://llvm.org/PR51753 + +#include +#include +#include + +struct MyBind { + int operator()(int x, int y) const { return 10*x + y; } +}; +template<> struct std::is_bind_expression : std::true_type {}; + +int main(int, char**) +{ + { + auto f = [](auto x) { return 10*x + 9; }; + MyBind bindexpr; + auto bound = std::bind(f, bindexpr); + assert(bound(7, 8) == 789); + } + { + auto f = [](auto x) { return 10*x + 9; }; + const MyBind bindexpr; + auto bound = std::bind(f, bindexpr); + assert(bound(7, 8) == 789); + } + { + auto f = [](auto x) { return 10*x + 9; }; + MyBind bindexpr; + auto bound = std::bind(f, std::move(bindexpr)); + assert(bound(7, 8) == 789); + } + { + auto f = [](auto x) { return 10*x + 9; }; + const MyBind bindexpr; + auto bound = std::bind(f, std::move(bindexpr)); + assert(bound(7, 8) == 789); + } + + return 0; +} Index: libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.isplace/is_placeholder.pass.cpp =================================================================== --- libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.isplace/is_placeholder.pass.cpp +++ libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.isplace/is_placeholder.pass.cpp @@ -18,8 +18,15 @@ test(const T&) { static_assert(std::is_placeholder::value == Expected, ""); + LIBCPP_STATIC_ASSERT(std::is_placeholder::value == Expected, ""); + LIBCPP_STATIC_ASSERT(std::is_placeholder::value == Expected, ""); + LIBCPP_STATIC_ASSERT(std::is_placeholder::value == Expected, ""); + #if TEST_STD_VER > 14 static_assert(std::is_placeholder_v == Expected, ""); + LIBCPP_STATIC_ASSERT(std::is_placeholder_v == Expected, ""); + LIBCPP_STATIC_ASSERT(std::is_placeholder_v == Expected, ""); + LIBCPP_STATIC_ASSERT(std::is_placeholder_v == Expected, ""); #endif } Index: libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.isplace/specialization.pass.cpp =================================================================== --- /dev/null +++ libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.isplace/specialization.pass.cpp @@ -0,0 +1,54 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11 + +// + +// template struct is_placeholder; +// A program may specialize this template for a program-defined type T +// to have a base characteristic of integral_constant with N > 0 +// to indicate that T should be treated as a placeholder type. +// https://llvm.org/PR51753 + +#include +#include +#include + +struct My2 {}; +template<> struct std::is_placeholder : std::integral_constant {}; + +int main(int, char**) +{ + { + auto f = [](auto x) { return 10*x + 9; }; + My2 place; + auto bound = std::bind(f, place); + assert(bound(7, 8) == 89); + } + { + auto f = [](auto x) { return 10*x + 9; }; + const My2 place; + auto bound = std::bind(f, place); + assert(bound(7, 8) == 89); + } + { + auto f = [](auto x) { return 10*x + 9; }; + My2 place; + auto bound = std::bind(f, std::move(place)); + assert(bound(7, 8) == 89); + } + { + auto f = [](auto x) { return 10*x + 9; }; + const My2 place; + auto bound = std::bind(f, std::move(place)); + assert(bound(7, 8) == 89); + } + + return 0; +}