//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
// <functional>
// INVOKE (f, t1, t2, ..., tN)
//------------------------------------------------------------------------------
// TESTING INVOKE(f, t1, t2, ..., tN)
// - Bullet 7 -- f(t2, ..., tN)
//
// Overview:
// Bullet 7 handles the cases where the first argument is not a member
// function.
//
// Concerns:
// 1) Different types of callable objects are supported. Including
// 1a) Free Function pointers and references.
// 1b) Classes which provide a call operator
// 1c) lambdas
// 2) The callable objects are perfect forwarded.
// 3) The arguments are perfect forwarded.
// 4) Signatures which include varargs are supported.
// 5) In C++03 3 extra arguments should be allowed.
//
// Plan:
// 1) Define a set of free functions, 'SF', and class types with call
// operators, 'SC', that address concerns 4 and 5. The free functions should
// return 'FunctionID::setUncheckedCall()' and the call operators should
// return 'MethodID::setUncheckedCall()'.
//
// 2) For each function 'f' in 'SF' and 'SC' attempt to call 'f'
// using the correct number of arguments and cv-ref qualifiers. Check that
// 'f' has been called using 'FunctionID::checkCall()' if 'f' is a free
// function and 'MethodID::checkCall()' otherwise.
#include <functional>
#include <type_traits>
#include <cassert>
#include "test_macros.h"
#include "invoke_helpers.h"
//==============================================================================
// freeFunction03 - A C++03 free function.
void*& freeFunction03() {
return FunctionPtrID<void*&(), freeFunction03>::setUncheckedCall();
}
void*& freeFunction03(...) {
return FunctionPtrID<void*&(...), freeFunction03>::setUncheckedCall();
}
template <class A0>
void*& freeFunction03(A0&) {
return FunctionPtrID<void*&(A0&), freeFunction03>::setUncheckedCall();
}
template <class A0>
void*& freeFunction03(A0&, ...) {
return FunctionPtrID<void*&(A0&, ...), freeFunction03>::setUncheckedCall();
}
template <class A0, class A1>
void*& freeFunction03(A0&, A1&) {
return FunctionPtrID<void*&(A0&, A1&), freeFunction03>::setUncheckedCall();
}
template <class A0, class A1>
void*& freeFunction03(A0&, A1&, ...) {
return FunctionPtrID<void*&(A0&, A1&, ...), freeFunction03>::setUncheckedCall();
}
template <class A0, class A1, class A2>
void*& freeFunction03(A0&, A1&, A2&) {
return FunctionPtrID<void*&(A0&, A1&, A2&), freeFunction03>::setUncheckedCall();
}
template <class A0, class A1, class A2>
void*& freeFunction03(A0&, A1&, A2&, ...) {
return FunctionPtrID<void*&(A0&, A1&, A2&, ...), freeFunction03>::setUncheckedCall();
}
//==============================================================================
// Functor03 - C++03 compatible functor object
struct Functor03 {
typedef void*& R;
typedef Functor03 C;
#define F(Args, ...) \
__VA_ARGS__ R operator() Args { return MethodID<R(C::*) Args>::setUncheckedCall(); } \
__VA_ARGS__ R operator() Args const { return MethodID<R(C::*) Args const>::setUncheckedCall(); } \
__VA_ARGS__ R operator() Args volatile { return MethodID<R(C::*) Args volatile>::setUncheckedCall(); } \
__VA_ARGS__ R operator() Args const volatile { return MethodID<R(C::*) Args const volatile>::setUncheckedCall(); }
#
F(())
F((A0&), template <class A0>)
F((A0&, A1&), template <class A0, class A1>)
F((A0&, A1&, A2&), template <class A0, class A1, class A2>)
#undef F
public:
Functor03() {}
private:
Functor03(Functor03 const&);
Functor03& operator=(Functor03 const&);
};
#if TEST_STD_VER >= 11
//==============================================================================
// freeFunction11 - A C++11 free function.
template <class ...Args>
void*& freeFunction11(Args&&...) {
return FunctionPtrID<void*&(Args&&...), freeFunction11>::setUncheckedCall();
}
template <class ...Args>
void*& freeFunction11(Args&&...,...) {
return FunctionPtrID<void*&(Args&&...,...), freeFunction11>::setUncheckedCall();
}
//==============================================================================
// Functor11 - C++11 reference qualified test member functions.
struct Functor11 {
typedef void*& R;
typedef Functor11 C;
#define F(CV) \
template <class ...Args> \
R operator()(Args&&...) CV { return MethodID<R(C::*)(Args&&...) CV>::setUncheckedCall(); }
#
F(&)
F(const &)
F(volatile &)
F(const volatile &)
F(&&)
F(const &&)
F(volatile &&)
F(const volatile &&)
#undef F
public:
Functor11() {}
private:
Functor11(Functor11 const&);
Functor11& operator=(Functor11 const&);
};
#endif // TEST_STD_VER >= 11
//==============================================================================
// TestCaseFunctorImp - A test case for an operator() class method.
// ClassType - The type of the call object.
// CallSig - The function signature of the call operator being tested.
// Arity - the arity of 'CallSig'
// ObjCaster - Transformation function applied to call object.
// ArgCaster - Transformation function applied to the extra arguments.
template <class ClassType, class CallSig, int Arity,
class ObjCaster, class ArgCaster = LValueCaster>
struct TestCaseFunctorImp {
public:
static void run() {
typedef MethodID<CallSig ClassType::*> MID;
BasicTest<MID, Arity, ObjCaster, ArgCaster> t;
typedef ClassType T;
typedef DerivedFromType<T> D;
T obj;
D der;
t.runTest(obj);
t.runTest(der);
}
};
//==============================================================================
// TestCaseFreeFunction - A test case for a free function.
// CallSig - The function signature of the free function being tested.
// FnPtr - The function being tested.
// Arity - the arity of 'CallSig'
// ArgCaster - Transformation function to be applied to the extra arguments.
template <class CallSig, CallSig* FnPtr, int Arity, class ArgCaster>
struct TestCaseFreeFunction {
public:
static void run() {
typedef FunctionPtrID<CallSig, FnPtr> FID;
BasicTest<FID, Arity, LValueCaster, ArgCaster> t;
DerefToType<CallSig*> deref_to(FnPtr);
DerefToType<CallSig&> deref_to_ref(*FnPtr);
t.runTest(FnPtr);
t.runTest(*FnPtr);
t.runTest(deref_to);
t.runTest(deref_to_ref);
}
};
//==============================================================================
// runTest Helpers
//==============================================================================
#if TEST_STD_VER >= 11
template <class Sig, int Arity, class ArgCaster>
void runFunctionTestCase11() {
TestCaseFreeFunction<Sig, freeFunction11, Arity, ArgCaster>();
}
#endif
template <class Sig, int Arity, class ArgCaster>
void runFunctionTestCase() {
TestCaseFreeFunction<Sig, freeFunction03, Arity, ArgCaster>();
#if TEST_STD_VER >= 11
runFunctionTestCase11<Sig, Arity, ArgCaster>();
#endif
}
template <class Sig, int Arity, class ObjCaster, class ArgCaster>
void runFunctorTestCase() {
TestCaseFunctorImp<Functor03, Sig, Arity, ObjCaster, ArgCaster>::run();
}
template <class Sig, int Arity, class ObjCaster>
void runFunctorTestCase() {
TestCaseFunctorImp<Functor03, Sig, Arity, ObjCaster>::run();
}
#if TEST_STD_VER >= 11
// runTestCase - Run a test case for C++11 class functor types
template <class Sig, int Arity, class ObjCaster, class ArgCaster = LValueCaster>
void runFunctorTestCase11() {
TestCaseFunctorImp<Functor11, Sig, Arity, ObjCaster, ArgCaster>::run();
}
#endif
// runTestCase - Run a test case for both function and functor types.
template <class Sig, int Arity, class ArgCaster>
void runTestCase() {
runFunctionTestCase<Sig, Arity, ArgCaster>();
runFunctorTestCase <Sig, Arity, LValueCaster, ArgCaster>();
};
int main(int, char**) {
typedef void*& R;
typedef ArgType A;
typedef A const CA;
runTestCase< R(), 0, LValueCaster >();
runTestCase< R(A&), 1, LValueCaster >();
runTestCase< R(A&, A&), 2, LValueCaster >();
runTestCase< R(A&, A&, A&), 3, LValueCaster >();
runTestCase< R(CA&), 1, ConstCaster >();
runTestCase< R(CA&, CA&), 2, ConstCaster >();
runTestCase< R(CA&, CA&, CA&), 3, ConstCaster >();
runFunctionTestCase<R(...), 0, LValueCaster >();
runFunctionTestCase<R(A&, ...), 1, LValueCaster >();
runFunctionTestCase<R(A&, A&, ...), 2, LValueCaster >();
runFunctionTestCase<R(A&, A&, A&, ...), 3, LValueCaster >();
#if TEST_STD_VER >= 11
runFunctionTestCase11<R(A&&), 1, MoveCaster >();
runFunctionTestCase11<R(A&&, ...), 1, MoveCaster >();
#endif
runFunctorTestCase<R(), 0, LValueCaster >();
runFunctorTestCase<R() const, 0, ConstCaster >();
runFunctorTestCase<R() volatile, 0, VolatileCaster >();
runFunctorTestCase<R() const volatile, 0, CVCaster >();
runFunctorTestCase<R(A&), 1, LValueCaster >();
runFunctorTestCase<R(A&) const, 1, ConstCaster >();
runFunctorTestCase<R(A&) volatile, 1, VolatileCaster >();
runFunctorTestCase<R(A&) const volatile, 1, CVCaster >();
runFunctorTestCase<R(A&, A&), 2, LValueCaster >();
runFunctorTestCase<R(A&, A&) const, 2, ConstCaster >();
runFunctorTestCase<R(A&, A&) volatile, 2, VolatileCaster >();
runFunctorTestCase<R(A&, A&) const volatile, 2, CVCaster >();
runFunctorTestCase<R(A&, A&, A&), 3, LValueCaster >();
runFunctorTestCase<R(A&, A&, A&) const, 3, ConstCaster >();
runFunctorTestCase<R(A&, A&, A&) volatile, 3, VolatileCaster >();
runFunctorTestCase<R(A&, A&, A&) const volatile, 3, CVCaster >();
{
typedef ConstCaster CC;
runFunctorTestCase<R(CA&), 1, LValueCaster, CC>();
runFunctorTestCase<R(CA&) const, 1, ConstCaster, CC>();
runFunctorTestCase<R(CA&) volatile, 1, VolatileCaster, CC>();
runFunctorTestCase<R(CA&) const volatile, 1, CVCaster, CC>();
runFunctorTestCase<R(CA&, CA&), 2, LValueCaster, CC>();
runFunctorTestCase<R(CA&, CA&) const, 2, ConstCaster, CC>();
runFunctorTestCase<R(CA&, CA&) volatile, 2, VolatileCaster, CC>();
runFunctorTestCase<R(CA&, CA&) const volatile, 2, CVCaster, CC>();
runFunctorTestCase<R(CA&, CA&, CA&), 3, LValueCaster, CC>();
runFunctorTestCase<R(CA&, CA&, CA&) const, 3, ConstCaster, CC>();
runFunctorTestCase<R(CA&, CA&, CA&) volatile, 3, VolatileCaster, CC>();
runFunctorTestCase<R(CA&, CA&, CA&) const volatile, 3, CVCaster, CC>();
}
#if TEST_STD_VER >= 11
runFunctorTestCase11<R() &, 0, LValueCaster >();
runFunctorTestCase11<R() const &, 0, ConstCaster >();
runFunctorTestCase11<R() volatile &, 0, VolatileCaster >();
runFunctorTestCase11<R() const volatile &, 0, CVCaster >();
runFunctorTestCase11<R() &&, 0, MoveCaster >();
runFunctorTestCase11<R() const &&, 0, MoveConstCaster >();
runFunctorTestCase11<R() volatile &&, 0, MoveVolatileCaster >();
runFunctorTestCase11<R() const volatile &&, 0, MoveCVCaster >();
{
typedef MoveCaster MC;
runFunctorTestCase11<R(A&&) &, 1, LValueCaster, MC>();
runFunctorTestCase11<R(A&&) const &, 1, ConstCaster, MC>();
runFunctorTestCase11<R(A&&) volatile &, 1, VolatileCaster, MC>();
runFunctorTestCase11<R(A&&) const volatile &, 1, CVCaster, MC>();
runFunctorTestCase11<R(A&&) &&, 1, MoveCaster, MC>();
runFunctorTestCase11<R(A&&) const &&, 1, MoveConstCaster, MC>();
runFunctorTestCase11<R(A&&) volatile &&, 1, MoveVolatileCaster, MC>();
runFunctorTestCase11<R(A&&) const volatile &&, 1, MoveCVCaster, MC>();
}
#endif
return 0;
}