diff --git a/libcxx/include/__functional/bind.h b/libcxx/include/__functional/bind.h --- a/libcxx/include/__functional/bind.h +++ b/libcxx/include/__functional/bind.h @@ -23,18 +23,24 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template struct __is_bind_expression : public false_type {}; -template struct _LIBCPP_TEMPLATE_VIS is_bind_expression - : public __is_bind_expression::type> {}; +template +struct is_bind_expression : _If< + _IsSame<_Tp, typename __uncvref<_Tp>::type>::value, + false_type, + is_bind_expression::type> +> {}; #if _LIBCPP_STD_VER > 14 template inline constexpr size_t is_bind_expression_v = is_bind_expression<_Tp>::value; #endif -template struct __is_placeholder : public integral_constant {}; -template struct _LIBCPP_TEMPLATE_VIS is_placeholder - : public __is_placeholder::type> {}; +template +struct is_placeholder : _If< + _IsSame<_Tp, typename __uncvref<_Tp>::type>::value, + integral_constant, + is_placeholder::type> +> {}; #if _LIBCPP_STD_VER > 14 template @@ -73,7 +79,7 @@ } // namespace placeholders template -struct __is_placeholder > +struct is_placeholder > : public integral_constant {}; @@ -304,7 +310,7 @@ }; template -struct __is_bind_expression<__bind<_Fp, _BoundArgs...> > : public true_type {}; +struct is_bind_expression<__bind<_Fp, _BoundArgs...> > : public true_type {}; template class __bind_r @@ -359,7 +365,7 @@ }; template -struct __is_bind_expression<__bind_r<_Rp, _Fp, _BoundArgs...> > : public true_type {}; +struct is_bind_expression<__bind_r<_Rp, _Fp, _BoundArgs...> > : public true_type {}; template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 diff --git a/libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.isbind/is_bind_expression.pass.cpp b/libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.isbind/is_bind_expression.pass.cpp --- a/libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.isbind/is_bind_expression.pass.cpp +++ b/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 } diff --git a/libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.isbind/specialization.pass.cpp b/libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.isbind/specialization.pass.cpp new file mode 100644 --- /dev/null +++ b/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; +} diff --git a/libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.isbind/is_placeholder.pass.cpp b/libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.isplace/is_placeholder.pass.cpp rename from libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.isbind/is_placeholder.pass.cpp rename to libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.isplace/is_placeholder.pass.cpp --- a/libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.isbind/is_placeholder.pass.cpp +++ b/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 } diff --git a/libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.isplace/specialization.pass.cpp b/libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.isplace/specialization.pass.cpp new file mode 100644 --- /dev/null +++ b/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; +}