mirror of
https://github.com/llvm-mirror/libcxx.git
synced 2025-10-23 01:18:52 +08:00
Add 'is_callable' and 'is_nothrow_callable' traits and cleanup INVOKE.
The primary purpose of this patch is to add the 'is_callable' traits. Since 'is_nothrow_callable' required making 'INVOKE' conditionally noexcept I also took this oppertunity to implement a constexpr version of INVOKE. This fixes 'std::experimental::apply' which required constexpr 'INVOKE support'. This patch will be followed up with some cleanup. Primarly removing most of "__member_function_traits" since it's no longer used by INVOKE (in C++11 at least). git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@266836 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <functional>
|
||||
|
||||
// template<CopyConstructible Fn, CopyConstructible... Types>
|
||||
// unspecified bind(Fn, Types...);
|
||||
// template<Returnable R, CopyConstructible Fn, CopyConstructible... Types>
|
||||
// unspecified bind(Fn, Types...);
|
||||
|
||||
// https://llvm.org/bugs/show_bug.cgi?id=23141
|
||||
#include <functional>
|
||||
#include <type_traits>
|
||||
|
||||
struct Fun
|
||||
{
|
||||
template<typename T, typename U>
|
||||
void operator()(T && t, U && u) const
|
||||
{
|
||||
static_assert(std::is_same<U, int &>::value, "");
|
||||
}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
std::bind(Fun{}, std::placeholders::_1, 42)("hello");
|
||||
}
|
@@ -260,8 +260,11 @@ void test_derived_from_ref_wrap() {
|
||||
DerivedFromRefWrap<int> d(x);
|
||||
auto get_fn = &std::reference_wrapper<int>::get;
|
||||
auto& ret = std::__invoke(get_fn, r);
|
||||
auto& cret = std::__invoke_constexpr(get_fn, r);
|
||||
assert(&ret == &x);
|
||||
assert(&cret == &x);
|
||||
auto& ret2 = std::__invoke(get_fn, d);
|
||||
auto& cret2 = std::__invoke_constexpr(get_fn, d);
|
||||
assert(&ret2 == &x);
|
||||
auto& ret3 = std::__invoke(get_fn, r2);
|
||||
assert(&ret3 == &x);
|
||||
|
@@ -185,11 +185,22 @@ private:
|
||||
#else
|
||||
void runTest(Fn M, T& obj, ObjectType* expect ) {
|
||||
#endif
|
||||
static_assert((std::is_same<
|
||||
decltype(std::__invoke(M, std::forward<T>(obj))), Expect
|
||||
>::value), "");
|
||||
Expect e = std::__invoke(M, std::forward<T>(obj));
|
||||
assert(&e == expect);
|
||||
{
|
||||
static_assert((std::is_same<
|
||||
decltype(std::__invoke(M, std::forward<T>(obj))), Expect
|
||||
>::value), "");
|
||||
Expect e = std::__invoke(M, std::forward<T>(obj));
|
||||
assert(&e == expect);
|
||||
}
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
static_assert((std::is_same<
|
||||
decltype(std::__invoke_constexpr(M, std::forward<T>(obj))), Expect
|
||||
>::value), "");
|
||||
Expect e = std::__invoke_constexpr(M, std::forward<T>(obj));
|
||||
assert(&e == expect);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -271,89 +271,185 @@ private:
|
||||
ArgType a0, a1, a2;
|
||||
|
||||
//==========================================================================
|
||||
// BULLET 1 AND 2 TEST METHODS
|
||||
// BULLET 1, 2 AND 3 TEST METHODS
|
||||
//==========================================================================
|
||||
template <class MethodPtr, class ObjectT>
|
||||
void runTestImp(Int<0>, MethodPtr ptr, ObjectT& object) {
|
||||
static_assert((std::is_same<
|
||||
decltype(std::__invoke(ptr, object_cast(object)))
|
||||
, CallRet>::value), "");
|
||||
assert(ID::unchecked_call == false);
|
||||
CallRet ret = std::__invoke(ptr, object_cast(object));
|
||||
assert(ID::checkCalled(ret));
|
||||
{
|
||||
static_assert((std::is_same<
|
||||
decltype(std::__invoke(ptr, object_cast(object)))
|
||||
, CallRet>::value), "");
|
||||
assert(ID::unchecked_call == false);
|
||||
CallRet ret = std::__invoke(ptr, object_cast(object));
|
||||
assert(ID::checkCalled(ret));
|
||||
}
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
static_assert((std::is_same<
|
||||
decltype(std::__invoke_constexpr(ptr, object_cast(object)))
|
||||
, CallRet>::value), "");
|
||||
assert(ID::unchecked_call == false);
|
||||
CallRet ret = std::__invoke_constexpr(ptr, object_cast(object));
|
||||
assert(ID::checkCalled(ret));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class MethodPtr, class ObjectT>
|
||||
void runTestImp(Int<1>, MethodPtr ptr, ObjectT& object) {
|
||||
static_assert((std::is_same<
|
||||
decltype(std::__invoke(ptr, object_cast(object), arg_cast(a0)))
|
||||
, CallRet>::value), "");
|
||||
assert(ID::unchecked_call == false);
|
||||
CallRet ret = std::__invoke(ptr, object_cast(object), arg_cast(a0));
|
||||
assert(ID::checkCalled(ret));
|
||||
{
|
||||
static_assert((std::is_same<
|
||||
decltype(std::__invoke(ptr, object_cast(object), arg_cast(a0)))
|
||||
, CallRet>::value), "");
|
||||
assert(ID::unchecked_call == false);
|
||||
CallRet ret = std::__invoke(ptr, object_cast(object), arg_cast(a0));
|
||||
assert(ID::checkCalled(ret));
|
||||
}
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
static_assert((std::is_same<
|
||||
decltype(std::__invoke_constexpr(ptr, object_cast(object), arg_cast(a0)))
|
||||
, CallRet>::value), "");
|
||||
assert(ID::unchecked_call == false);
|
||||
CallRet ret = std::__invoke_constexpr(ptr, object_cast(object), arg_cast(a0));
|
||||
assert(ID::checkCalled(ret));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class MethodPtr, class ObjectT>
|
||||
void runTestImp(Int<2>, MethodPtr ptr, ObjectT& object) {
|
||||
static_assert((std::is_same<
|
||||
decltype(std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1)))
|
||||
, CallRet>::value), "");
|
||||
assert(ID::unchecked_call == false);
|
||||
CallRet ret = std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1));
|
||||
assert(ID::checkCalled(ret));
|
||||
{
|
||||
static_assert((std::is_same<
|
||||
decltype(std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1)))
|
||||
, CallRet>::value), "");
|
||||
assert(ID::unchecked_call == false);
|
||||
CallRet ret = std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1));
|
||||
assert(ID::checkCalled(ret));
|
||||
}
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
static_assert((std::is_same<
|
||||
decltype(std::__invoke_constexpr(ptr, object_cast(object), arg_cast(a0), arg_cast(a1)))
|
||||
, CallRet>::value), "");
|
||||
assert(ID::unchecked_call == false);
|
||||
CallRet ret = std::__invoke_constexpr(ptr, object_cast(object), arg_cast(a0), arg_cast(a1));
|
||||
assert(ID::checkCalled(ret));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class MethodPtr, class ObjectT>
|
||||
void runTestImp(Int<3>, MethodPtr ptr, ObjectT& object) {
|
||||
static_assert((std::is_same<
|
||||
decltype(std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2)))
|
||||
, CallRet>::value), "");
|
||||
assert(ID::unchecked_call == false);
|
||||
CallRet ret = std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2));
|
||||
assert(ID::checkCalled(ret));
|
||||
{
|
||||
static_assert((std::is_same<
|
||||
decltype(std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2)))
|
||||
, CallRet>::value), "");
|
||||
assert(ID::unchecked_call == false);
|
||||
CallRet ret = std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2));
|
||||
assert(ID::checkCalled(ret));
|
||||
}
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
static_assert((std::is_same<
|
||||
decltype(std::__invoke_constexpr(ptr, object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2)))
|
||||
, CallRet>::value), "");
|
||||
assert(ID::unchecked_call == false);
|
||||
CallRet ret = std::__invoke_constexpr(ptr, object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2));
|
||||
assert(ID::checkCalled(ret));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
// BULLET 5 TEST METHODS
|
||||
// BULLET 7 TEST METHODS
|
||||
//==========================================================================
|
||||
template <class ObjectT>
|
||||
void runTestImp(Int<0>, ObjectT& object) {
|
||||
static_assert((std::is_same<
|
||||
decltype(std::__invoke(object_cast(object)))
|
||||
, CallRet>::value), "");
|
||||
assert(ID::unchecked_call == false);
|
||||
CallRet ret = std::__invoke(object_cast(object));
|
||||
assert(ID::checkCalled(ret));
|
||||
{
|
||||
static_assert((std::is_same<
|
||||
decltype(std::__invoke(object_cast(object)))
|
||||
, CallRet>::value), "");
|
||||
assert(ID::unchecked_call == false);
|
||||
CallRet ret = std::__invoke(object_cast(object));
|
||||
assert(ID::checkCalled(ret));
|
||||
}
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
static_assert((std::is_same<
|
||||
decltype(std::__invoke_constexpr(object_cast(object)))
|
||||
, CallRet>::value), "");
|
||||
assert(ID::unchecked_call == false);
|
||||
CallRet ret = std::__invoke_constexpr(object_cast(object));
|
||||
assert(ID::checkCalled(ret));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class ObjectT>
|
||||
void runTestImp(Int<1>, ObjectT& object) {
|
||||
static_assert((std::is_same<
|
||||
decltype(std::__invoke(object_cast(object), arg_cast(a0)))
|
||||
, CallRet>::value), "");
|
||||
assert(ID::unchecked_call == false);
|
||||
CallRet ret = std::__invoke(object_cast(object), arg_cast(a0));
|
||||
assert(ID::checkCalled(ret));
|
||||
{
|
||||
static_assert((std::is_same<
|
||||
decltype(std::__invoke(object_cast(object), arg_cast(a0)))
|
||||
, CallRet>::value), "");
|
||||
assert(ID::unchecked_call == false);
|
||||
CallRet ret = std::__invoke(object_cast(object), arg_cast(a0));
|
||||
assert(ID::checkCalled(ret));
|
||||
}
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
static_assert((std::is_same<
|
||||
decltype(std::__invoke_constexpr(object_cast(object), arg_cast(a0)))
|
||||
, CallRet>::value), "");
|
||||
assert(ID::unchecked_call == false);
|
||||
CallRet ret = std::__invoke_constexpr(object_cast(object), arg_cast(a0));
|
||||
assert(ID::checkCalled(ret));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class ObjectT>
|
||||
void runTestImp(Int<2>, ObjectT& object) {
|
||||
static_assert((std::is_same<
|
||||
decltype(std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1)))
|
||||
, CallRet>::value), "");
|
||||
assert(ID::unchecked_call == false);
|
||||
CallRet ret = std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1));
|
||||
assert(ID::checkCalled(ret));
|
||||
{
|
||||
static_assert((std::is_same<
|
||||
decltype(std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1)))
|
||||
, CallRet>::value), "");
|
||||
assert(ID::unchecked_call == false);
|
||||
CallRet ret = std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1));
|
||||
assert(ID::checkCalled(ret));
|
||||
}
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
static_assert((std::is_same<
|
||||
decltype(std::__invoke_constexpr(object_cast(object), arg_cast(a0), arg_cast(a1)))
|
||||
, CallRet>::value), "");
|
||||
assert(ID::unchecked_call == false);
|
||||
CallRet ret = std::__invoke_constexpr(object_cast(object), arg_cast(a0), arg_cast(a1));
|
||||
assert(ID::checkCalled(ret));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class ObjectT>
|
||||
void runTestImp(Int<3>, ObjectT& object) {
|
||||
static_assert((std::is_same<
|
||||
decltype(std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2)))
|
||||
, CallRet>::value), "");
|
||||
assert(ID::unchecked_call == false);
|
||||
CallRet ret = std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2));
|
||||
assert(ID::checkCalled(ret));
|
||||
{
|
||||
static_assert((std::is_same<
|
||||
decltype(std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2)))
|
||||
, CallRet>::value), "");
|
||||
assert(ID::unchecked_call == false);
|
||||
CallRet ret = std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2));
|
||||
assert(ID::checkCalled(ret));
|
||||
}
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
static_assert((std::is_same<
|
||||
decltype(std::__invoke_constexpr(object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2)))
|
||||
, CallRet>::value), "");
|
||||
assert(ID::unchecked_call == false);
|
||||
CallRet ret = std::__invoke_constexpr(object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2));
|
||||
assert(ID::checkCalled(ret));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user