summaryrefslogtreecommitdiffstats
path: root/libcxx/test/std/utilities/function.objects/func.require
diff options
context:
space:
mode:
authorEric Fiselier <eric@efcs.ca>2016-04-18 06:17:30 +0000
committerEric Fiselier <eric@efcs.ca>2016-04-18 06:17:30 +0000
commit2152fd7682e3725449fc6483141dc55fc80dad16 (patch)
treeffc09c3c81b33127dc7ea73eccf76d9b8272de4a /libcxx/test/std/utilities/function.objects/func.require
parent76a7ca0f67379705773c4d1da89e546667ff25f2 (diff)
downloadbcm5719-llvm-2152fd7682e3725449fc6483141dc55fc80dad16.tar.gz
bcm5719-llvm-2152fd7682e3725449fc6483141dc55fc80dad16.zip
Implement LWG issue 2219 - support reference_wrapper in INVOKE
llvm-svn: 266590
Diffstat (limited to 'libcxx/test/std/utilities/function.objects/func.require')
-rw-r--r--libcxx/test/std/utilities/function.objects/func.require/bullet_1_2_3.pass.cpp (renamed from libcxx/test/std/utilities/function.objects/func.require/bullet_1_and_2.pass.cpp)79
-rw-r--r--libcxx/test/std/utilities/function.objects/func.require/bullet_4_5_6.pass.cpp (renamed from libcxx/test/std/utilities/function.objects/func.require/bullet_3_and_4.pass.cpp)77
-rw-r--r--libcxx/test/std/utilities/function.objects/func.require/bullet_7.pass.cpp (renamed from libcxx/test/std/utilities/function.objects/func.require/bullet_5.pass.cpp)4
-rw-r--r--libcxx/test/std/utilities/function.objects/func.require/invoke_helpers.h34
4 files changed, 159 insertions, 35 deletions
diff --git a/libcxx/test/std/utilities/function.objects/func.require/bullet_1_and_2.pass.cpp b/libcxx/test/std/utilities/function.objects/func.require/bullet_1_2_3.pass.cpp
index e579f207a33..09e8e21137a 100644
--- a/libcxx/test/std/utilities/function.objects/func.require/bullet_1_and_2.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/func.require/bullet_1_2_3.pass.cpp
@@ -14,12 +14,14 @@
//------------------------------------------------------------------------------
// TESTING INVOKE(f, t1, t2, ..., tN)
// - Bullet 1 -- (t1.*f)(t2, ..., tN)
-// - Bullet 2 -- ((*t1).*f)(t2, ..., tN)
+// - Bullet 2 -- (t1.get().*f)(t2, ..., tN) // t1 is a reference_wrapper
+// - Bullet 3 -- ((*t1).*f)(t2, ..., tN)
//
// Overview:
-// Bullets 1 and 2 handle the case where 'f' is a pointer to member function.
+// Bullets 1, 2 and 3 handle the case where 'f' is a pointer to member function.
// Bullet 1 only handles the cases where t1 is an object of type T or a
-// type derived from 'T'. Bullet 2 handles all other cases.
+// type derived from 'T'. Bullet 2 handles the case where 't1' is a reference
+// wrapper and bullet 3 handles all other cases.
//
// Concerns:
// 1) cv-qualified member function signatures are accepted.
@@ -31,6 +33,7 @@
// as the call object.
// 7) Pointers to T or a type derived from T can be used as the call object.
// 8) Reference return types are properly deduced.
+// 9) reference_wrappers are properly handled and unwrapped.
//
//
// Plan:
@@ -123,6 +126,7 @@ private:
#endif // TEST_STD_VER >= 11
+
//==============================================================================
// TestCase - A test case for a single member function.
// ClassType - The type of the class being tested.
@@ -151,6 +155,8 @@ private:
D* der_ptr = &der;
DerefToType<T> dref;
DerefPropType<T> dref2;
+ std::reference_wrapper<T> rref(obj);
+ std::reference_wrapper<D> drref(der);
// (Plan-3) Dispatch based on the CV tags.
CV tag;
@@ -158,9 +164,13 @@ private:
runTestDispatch(tag, obj);
runTestDispatch(tag, der);
runTestDispatch(tag, dref2);
- runTestDispatchIf(NotRValue, tag, dref);
- runTestDispatchIf(NotRValue, tag, obj_ptr);
+ runTestDispatchIf(NotRValue, tag, dref);
+ runTestDispatchIf(NotRValue, tag, obj_ptr);
runTestDispatchIf(NotRValue, tag, der_ptr);
+#if TEST_STD_VER >= 11
+ runTestDispatchIf(NotRValue, tag, rref);
+ runTestDispatchIf(NotRValue, tag, drref);
+#endif
}
template <class QT, class Tp>
@@ -179,27 +189,43 @@ private:
template <class Tp>
void runTestDispatch(Q_Const, Tp& v) {
- Tp const& cv = v;
runTest(v);
- runTest(cv);
+ runTest(makeConst(v));
}
template <class Tp>
void runTestDispatch(Q_Volatile, Tp& v) {
- Tp volatile& vv = v;
runTest(v);
- runTest(vv);
+ runTest(makeVolatile(v));
+
}
template <class Tp>
void runTestDispatch(Q_CV, Tp& v) {
- Tp const& cv = v;
- Tp volatile& vv = v;
- Tp const volatile& cvv = v;
runTest(v);
- runTest(cv);
- runTest(vv);
- runTest(cvv);
+ runTest(makeConst(v));
+ runTest(makeVolatile(v));
+ runTest(makeCV(v));
+ }
+
+ template <class T>
+ void runTest(const std::reference_wrapper<T>& obj) {
+ typedef Caster<Q_None, RValue> SCast;
+ typedef Caster<Q_None, ArgRValue> ACast;
+ typedef CallSig (ClassType::*MemPtr);
+ // Delegate test to logic in invoke_helpers.h
+ BasicTest<MethodID<MemPtr>, Arity, SCast, ACast> b;
+ b.runTest( (MemPtr)&ClassType::f, obj);
+ }
+
+ template <class T>
+ void runTest(T* obj) {
+ typedef Caster<Q_None, RValue> SCast;
+ typedef Caster<Q_None, ArgRValue> ACast;
+ typedef CallSig (ClassType::*MemPtr);
+ // Delegate test to logic in invoke_helpers.h
+ BasicTest<MethodID<MemPtr>, Arity, SCast, ACast> b;
+ b.runTest( (MemPtr)&ClassType::f, obj);
}
template <class Obj>
@@ -221,6 +247,27 @@ template <class Sig, int Arity, class CV, bool RValue = false>
struct TestCase11 : public TestCaseImp<MemFun11, Sig, Arity, CV, RValue, true> {};
#endif
+template <class Tp>
+struct DerivedFromRefWrap : public std::reference_wrapper<Tp> {
+ DerivedFromRefWrap(Tp& tp) : std::reference_wrapper<Tp>(tp) {}
+};
+
+#if TEST_STD_VER >= 11
+void test_derived_from_ref_wrap() {
+ int x = 42;
+ std::reference_wrapper<int> r(x);
+ std::reference_wrapper<std::reference_wrapper<int>> r2(r);
+ DerivedFromRefWrap<int> d(x);
+ auto get_fn = &std::reference_wrapper<int>::get;
+ auto& ret = std::__invoke(get_fn, r);
+ assert(&ret == &x);
+ auto& ret2 = std::__invoke(get_fn, d);
+ assert(&ret2 == &x);
+ auto& ret3 = std::__invoke(get_fn, r2);
+ assert(&ret3 == &x);
+}
+#endif
+
int main() {
typedef void*& R;
typedef ArgType A;
@@ -314,5 +361,7 @@ int main() {
TestCase11<R(A&&, A&&, A&&, ...) const &&, 3, Q_Const, /* RValue */ true>::run();
TestCase11<R(A&&, A&&, A&&, ...) volatile &&, 3, Q_Volatile, /* RValue */ true>::run();
TestCase11<R(A&&, A&&, A&&, ...) const volatile &&, 3, Q_CV, /* RValue */ true>::run();
+
+ test_derived_from_ref_wrap();
#endif
} \ No newline at end of file
diff --git a/libcxx/test/std/utilities/function.objects/func.require/bullet_3_and_4.pass.cpp b/libcxx/test/std/utilities/function.objects/func.require/bullet_4_5_6.pass.cpp
index b6fe190bd2a..2007c417a62 100644
--- a/libcxx/test/std/utilities/function.objects/func.require/bullet_3_and_4.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/func.require/bullet_4_5_6.pass.cpp
@@ -13,13 +13,15 @@
//------------------------------------------------------------------------------
// TESTING INVOKE(f, t1, t2, ..., tN)
-// - Bullet 3 -- t1.*f
-// - Bullet 4 -- (*t1).*f
+// - Bullet 4 -- t1.*f
+// - Bullet 5 -- t1.get().*f // t1 is a reference wrapper.
+// - Bullet 6 -- (*t1).*f
//
// Overview:
-// Bullets 3 and 4 handle the case where 'f' is a pointer to member object.
-// Bullet 3 only handles the cases where t1 is an object of type T or a
-// type derived from 'T'. Bullet 4 handles all other cases.
+// Bullets 4, 5 and 6 handle the case where 'f' is a pointer to member object.
+// Bullet 4 only handles the cases where t1 is an object of type T or a
+// type derived from 'T'. Bullet 5 handles cases where 't1' is a reference_wrapper
+// and bullet 6 handles all other cases.
//
// Concerns:
// 1) The return type is always an lvalue reference.
@@ -30,6 +32,7 @@
// 6) All types that dereference to T or a type derived from T can be used
// as the call object.
// 7) Pointers to T or a type derived from T can be used as the call object.
+// 8) reference_wrapper's are properly unwrapped before invoking the function.
#include <functional>
#include <type_traits>
@@ -66,6 +69,8 @@ private:
Derived* der_ptr = &der;
DerefToType<TestType> dref;
DerefPropType<TestType> dref2;
+ std::reference_wrapper<TestType> rref(obj);
+ std::reference_wrapper<Derived> drref(der);
{
typedef ObjectType (TestType::*MemPtr);
@@ -74,9 +79,13 @@ private:
runTestDispatch<E>(M, obj, &obj.object);
runTestDispatch<E>(M, der, &der.object);
runTestDispatch<E>(M, dref2, &dref2.object.object);
- runTestPointerDispatch<E>(M, obj_ptr, &obj_ptr->object);
- runTestPointerDispatch<E>(M, der_ptr, &der_ptr->object);
- runTestPointerDispatch<E>(M, dref, &dref.object.object);
+ runTestPropCVDispatch<E>(M, obj_ptr, &obj_ptr->object);
+ runTestPropCVDispatch<E>(M, der_ptr, &der_ptr->object);
+#if TEST_STD_VER >= 11
+ runTestPropCVDispatch<E>(M, rref, &(rref.get().object));
+ runTestPropCVDispatch<E>(M, drref, &(drref.get().object));
+#endif
+ runTestNoPropDispatch<E>(M, dref, &dref.object.object);
}
{
typedef ObjectType const (TestType::*CMemPtr);
@@ -85,9 +94,13 @@ private:
runTestDispatch<E>(M, obj, &obj.object);
runTestDispatch<E>(M, der, &der.object);
runTestDispatch<E>(M, dref2, &dref2.object.object);
- runTestPointerDispatch<E>(M, obj_ptr, &obj_ptr->object);
- runTestPointerDispatch<E>(M, der_ptr, &der_ptr->object);
- runTestPointerDispatch<E>(M, dref, &dref.object.object);
+ runTestPropCVDispatch<E>(M, obj_ptr, &obj_ptr->object);
+ runTestPropCVDispatch<E>(M, der_ptr, &der_ptr->object);
+#if TEST_STD_VER >= 11
+ runTestPropCVDispatch<E>(M, rref, &(rref.get().object));
+ runTestPropCVDispatch<E>(M, drref, &(drref.get().object));
+#endif
+ runTestNoPropDispatch<E>(M, dref, &dref.object.object);
}
{
typedef ObjectType volatile (TestType::*VMemPtr);
@@ -96,9 +109,13 @@ private:
runTestDispatch<E>(M, obj, &obj.object);
runTestDispatch<E>(M, der, &der.object);
runTestDispatch<E>(M, dref2, &dref2.object.object);
- runTestPointerDispatch<E>(M, obj_ptr, &obj_ptr->object);
- runTestPointerDispatch<E>(M, der_ptr, &der_ptr->object);
- runTestPointerDispatch<E>(M, dref, &dref.object.object);
+ runTestPropCVDispatch<E>(M, obj_ptr, &obj_ptr->object);
+ runTestPropCVDispatch<E>(M, der_ptr, &der_ptr->object);
+#if TEST_STD_VER >= 11
+ runTestPropCVDispatch<E>(M, rref, &(rref.get().object));
+ runTestPropCVDispatch<E>(M, drref, &(drref.get().object));
+#endif
+ runTestNoPropDispatch<E>(M, dref, &dref.object.object);
}
{
typedef ObjectType const volatile (TestType::*CVMemPtr);
@@ -107,9 +124,13 @@ private:
runTestDispatch<E>(M, obj, &obj.object);
runTestDispatch<E>(M, der, &der.object);
runTestDispatch<E>(M, dref2, &dref2.object.object);
- runTestPointerDispatch<E>(M, obj_ptr, &obj_ptr->object);
- runTestPointerDispatch<E>(M, der_ptr, &der_ptr->object);
- runTestPointerDispatch<E>(M, dref, &dref.object.object);
+ runTestPropCVDispatch<E>(M, obj_ptr, &obj_ptr->object);
+ runTestPropCVDispatch<E>(M, der_ptr, &der_ptr->object);
+#if TEST_STD_VER >= 11
+ runTestPropCVDispatch<E>(M, rref, &(rref.get().object));
+ runTestPropCVDispatch<E>(M, drref, &(drref.get().object));
+#endif
+ runTestNoPropDispatch<E>(M, dref, &dref.object.object);
}
}
@@ -128,7 +149,15 @@ private:
}
template <class Expect, class Fn, class T>
- void runTestPointerDispatch(Fn M, T& obj, ObjectType* expect) {
+ void runTestPropCVDispatch(Fn M, T& obj, ObjectType* expect) {
+ runTest<Expect &> (M, obj, expect);
+ runTest<Expect const&> (M, makeConst(obj), expect);
+ runTest<Expect volatile&> (M, makeVolatile(obj), expect);
+ runTest<Expect const volatile&>(M, makeCV(obj), expect);
+ }
+
+ template <class Expect, class Fn, class T>
+ void runTestNoPropDispatch(Fn M, T& obj, ObjectType* expect) {
runTest<Expect&>(M, C_<T &>(obj), expect);
runTest<Expect&>(M, C_<T const&>(obj), expect);
runTest<Expect&>(M, C_<T volatile&>(obj), expect);
@@ -142,6 +171,15 @@ private:
}
template <class Expect, class Fn, class T>
+ void runTest(Fn M, const T& obj, ObjectType* expect) {
+ static_assert((std::is_same<
+ decltype(std::__invoke(M, obj)), Expect
+ >::value), "");
+ Expect e = std::__invoke(M, obj);
+ assert(&e == expect);
+ }
+
+ template <class Expect, class Fn, class T>
#if TEST_STD_VER >= 11
void runTest(Fn M, T&& obj, ObjectType* expect) {
#else
@@ -155,6 +193,9 @@ private:
}
};
+
+
+
int main() {
TestCase<ArgType>::run();
TestCase<ArgType const>::run();
diff --git a/libcxx/test/std/utilities/function.objects/func.require/bullet_5.pass.cpp b/libcxx/test/std/utilities/function.objects/func.require/bullet_7.pass.cpp
index 3f3c96a9b9b..0d14a350c89 100644
--- a/libcxx/test/std/utilities/function.objects/func.require/bullet_5.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/func.require/bullet_7.pass.cpp
@@ -13,10 +13,10 @@
//------------------------------------------------------------------------------
// TESTING INVOKE(f, t1, t2, ..., tN)
-// - Bullet 5 -- f(t2, ..., tN)
+// - Bullet 7 -- f(t2, ..., tN)
//
// Overview:
-// Bullet 5 handles the cases where the first argument is not a member
+// Bullet 7 handles the cases where the first argument is not a member
// function.
//
// Concerns:
diff --git a/libcxx/test/std/utilities/function.objects/func.require/invoke_helpers.h b/libcxx/test/std/utilities/function.objects/func.require/invoke_helpers.h
index a85b39f3717..495703d0e32 100644
--- a/libcxx/test/std/utilities/function.objects/func.require/invoke_helpers.h
+++ b/libcxx/test/std/utilities/function.objects/func.require/invoke_helpers.h
@@ -79,6 +79,40 @@ typedef Caster<Q_Const, true> MoveConstCaster;
typedef Caster<Q_Volatile, true> MoveVolatileCaster;
typedef Caster<Q_CV, true> MoveCVCaster;
+
+template <class Tp>
+Tp const& makeConst(Tp& ref) { return ref; }
+
+template <class Tp>
+Tp const* makeConst(Tp* ptr) { return ptr; }
+
+template <class Tp>
+std::reference_wrapper<const Tp> makeConst(std::reference_wrapper<Tp>& ref) {
+ return std::reference_wrapper<const Tp>(ref.get());
+}
+
+template <class Tp>
+Tp volatile& makeVolatile(Tp& ref) { return ref; }
+
+template <class Tp>
+Tp volatile* makeVolatile(Tp* ptr) { return ptr; }
+
+template <class Tp>
+std::reference_wrapper<volatile Tp> makeVolatile(std::reference_wrapper<Tp>& ref) {
+ return std::reference_wrapper<volatile Tp>(ref.get());
+}
+
+template <class Tp>
+Tp const volatile& makeCV(Tp& ref) { return ref; }
+
+template <class Tp>
+Tp const volatile* makeCV(Tp* ptr) { return ptr; }
+
+template <class Tp>
+std::reference_wrapper<const volatile Tp> makeCV(std::reference_wrapper<Tp>& ref) {
+ return std::reference_wrapper<const volatile Tp>(ref.get());
+}
+
// A shorter name for 'static_cast'
template <class QualType, class Tp>
QualType C_(Tp& v) { return static_cast<QualType>(v); };
OpenPOWER on IntegriCloud