111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//===----------------------------------------------------------------------===//
211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//
311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//                     The LLVM Compiler Infrastructure
411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//
511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// This file is dual licensed under the MIT and the University of Illinois Open
611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Source Licenses. See LICENSE.TXT for details.
711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//
811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//===----------------------------------------------------------------------===//
911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
1011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifndef INVOKE_HELPERS_H
1111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#define INVOKE_HELPERS_H
1211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
1311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <type_traits>
1411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <cassert>
1511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <functional>
1611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
1711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "test_macros.h"
1811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
1911cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <int I>
2011cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstruct Int : public std::integral_constant<int, I> {};
2111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
2211cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <bool P>
2311cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstruct Bool : public std::integral_constant<bool, P> {};
2411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
2511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstruct Q_None {
2611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    template <class T>
2711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    struct apply { typedef T type; };
2811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert};
2911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
3011cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstruct Q_Const {
3111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    template <class T>
3211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    struct apply { typedef T const type; };
3311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert};
3411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
3511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstruct Q_Volatile {
3611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    template <class T>
3711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    struct apply { typedef T volatile type; };
3811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert};
3911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
4011cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstruct Q_CV {
4111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    template <class T>
4211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    struct apply { typedef T const volatile type; };
4311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert};
4411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
4511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Caster - A functor object that performs cv-qualifier and value category
4611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//   conversions.
4711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//   QualTag - A metafunction type that applies cv-qualifiers to its argument.
4811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//   RValue - True if the resulting object should be an RValue reference.
4911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//            False otherwise.
5011cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <class QualTag, bool RValue = false>
5111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstruct Caster {
5211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    template <class T>
5311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    struct apply {
5411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        typedef typename std::remove_reference<T>::type RawType;
5511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        typedef typename QualTag::template apply<RawType>::type CVType;
5611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if TEST_STD_VER >= 11
5711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        typedef typename std::conditional<RValue,
5811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            CVType&&, CVType&
5911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        >::type type;
6011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#else
6111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        typedef CVType& type;
6211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif
6311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    };
6411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
6511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    template <class T>
6611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    typename apply<T>::type
6711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    operator()(T& obj) const {
6811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        typedef typename apply<T>::type OutType;
6911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return static_cast<OutType>(obj);
7011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
7111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert};
7211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
7311cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttypedef Caster<Q_None>           LValueCaster;
7411cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttypedef Caster<Q_Const>          ConstCaster;
7511cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttypedef Caster<Q_Volatile>       VolatileCaster;
7611cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttypedef Caster<Q_CV>             CVCaster;
7711cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttypedef Caster<Q_None,     true> MoveCaster;
7811cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttypedef Caster<Q_Const,    true> MoveConstCaster;
7911cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttypedef Caster<Q_Volatile, true> MoveVolatileCaster;
8011cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttypedef Caster<Q_CV,       true> MoveCVCaster;
8111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
8211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
8311cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <class Tp>
8411cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertTp const& makeConst(Tp& ref) { return ref; }
8511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
8611cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <class Tp>
8711cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertTp const* makeConst(Tp* ptr) { return ptr; }
8811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
8911cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <class Tp>
9011cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstd::reference_wrapper<const Tp> makeConst(std::reference_wrapper<Tp>& ref) {
9111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return std::reference_wrapper<const Tp>(ref.get());
9211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
9311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
9411cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <class Tp>
9511cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertTp volatile& makeVolatile(Tp& ref) { return ref; }
9611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
9711cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <class Tp>
9811cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertTp volatile* makeVolatile(Tp* ptr) { return ptr; }
9911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
10011cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <class Tp>
10111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstd::reference_wrapper<volatile Tp> makeVolatile(std::reference_wrapper<Tp>& ref) {
10211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return std::reference_wrapper<volatile Tp>(ref.get());
10311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
10411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
10511cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <class Tp>
10611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertTp const volatile& makeCV(Tp& ref) { return ref; }
10711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
10811cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <class Tp>
10911cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertTp const volatile* makeCV(Tp* ptr) { return ptr; }
11011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
11111cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <class Tp>
11211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstd::reference_wrapper<const volatile Tp> makeCV(std::reference_wrapper<Tp>& ref) {
11311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return std::reference_wrapper<const volatile Tp>(ref.get());
11411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
11511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
11611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// A shorter name for 'static_cast'
11711cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <class QualType, class Tp>
11811cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertQualType C_(Tp& v) { return static_cast<QualType>(v); };
11911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
12011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//==============================================================================
12111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// ArgType - A non-copyable type intended to be used as a dummy argument type
12211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//   to test functions.
12311cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstruct ArgType {
12411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    int value;
12511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    explicit ArgType(int val = 0) : value(val) {}
12611cd02dfb91661c65134cac258cf5924270e9d2Dan Albertprivate:
12711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    ArgType(ArgType const&);
12811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    ArgType& operator=(ArgType const&);
12911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert};
13011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
13111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//==============================================================================
13211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// DerivedFromBase - A type that derives from it's template argument 'Base'
13311cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <class Base>
13411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstruct DerivedFromType : public Base {
13511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    DerivedFromType() : Base() {}
13611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    template <class Tp>
13711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    explicit DerivedFromType(Tp const& t) : Base(t) {}
13811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert};
13911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
14011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//==============================================================================
14111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// DerefToType - A type that dereferences to it's template argument 'To'.
14211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//   The cv-ref qualifiers of the 'DerefToType' object do not propagate
14311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//   to the resulting 'To' object.
14411cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <class To>
14511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstruct DerefToType {
14611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    To object;
14711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
14811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    DerefToType() {}
14911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
15011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    template <class Up>
15111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    explicit DerefToType(Up const& val) : object(val) {}
15211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
15311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    To& operator*() const volatile { return const_cast<To&>(object); }
15411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert};
15511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
15611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//==============================================================================
15711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// DerefPropToType - A type that dereferences to it's template argument 'To'.
15811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//   The cv-ref qualifiers of the 'DerefPropToType' object propagate
15911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//   to the resulting 'To' object.
16011cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <class To>
16111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstruct DerefPropType {
16211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    To object;
16311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
16411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    DerefPropType() {}
16511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
16611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    template <class Up>
16711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    explicit DerefPropType(Up const& val) : object(val) {}
16811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
16911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if TEST_STD_VER < 11
17011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    To& operator*() { return object; }
17111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    To const& operator*() const { return object; }
17211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    To volatile& operator*() volatile  { return object; }
17311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    To const volatile& operator*() const volatile { return object; }
17411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#else
17511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    To& operator*() & { return object; }
17611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    To const& operator*() const & { return object; }
17711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    To volatile& operator*() volatile  & { return object; }
17811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    To const volatile& operator*() const volatile & { return object; }
17911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    To&& operator*() && { return static_cast<To &&>(object); }
18011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    To const&& operator*() const && { return static_cast<To const&&>(object); }
18111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    To volatile&& operator*() volatile  && { return static_cast<To volatile&&>(object); }
18211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    To const volatile&& operator*() const volatile && { return static_cast<To const volatile&&>(object); }
18311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif
18411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert};
18511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
18611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//==============================================================================
18711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// MethodID - A type that uniquely identifies a member function for a class.
18811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//   This type is used to communicate between the member functions being tested
18911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//   and the tests invoking them.
19011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// - Test methods should call 'setUncheckedCall()' whenever they are invoked.
19111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// - Tests consume the unchecked call using checkCall(<return-value>)` to assert
19211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//   that the method has been called and that the return value of `__invoke`
19311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//   matches what the method actually returned.
19411cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <class T>
19511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstruct MethodID {
19611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    typedef void* IDType;
19711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
19811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    static int dummy; // A dummy memory location.
19911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    static void* id; // The "ID" is the value of this pointer.
20011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    static bool unchecked_call; // Has a call happened that has not been checked.
20111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
20211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    static void*& setUncheckedCall() {
20311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        assert(unchecked_call == false);
20411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        unchecked_call = true;
20511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return id;
20611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
20711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
20811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    static bool checkCalled(void*& return_value) {
20911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        bool old = unchecked_call;
21011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        unchecked_call = false;
21111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return old && id == return_value && &id == &return_value;
21211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
21311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert};
21411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
21511cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <class T> int   MethodID<T>::dummy = 0;
21611cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <class T> void* MethodID<T>::id = (void*)&MethodID<T>::dummy;
21711cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <class T> bool  MethodID<T>::unchecked_call = false;
21811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
21911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
22011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//==============================================================================
22111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// FunctionPtrID - Like MethodID but for free function pointers.
22211cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <class T, T*>
22311cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstruct FunctionPtrID {
22411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    static int dummy; // A dummy memory location.
22511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    static void* id; // The "ID" is the value of this pointer.
22611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    static bool unchecked_call; // Has a call happened that has not been checked.
22711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
22811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    static void*& setUncheckedCall() {
22911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        assert(unchecked_call == false);
23011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        unchecked_call = true;
23111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return id;
23211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
23311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
23411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    static bool checkCalled(void*& return_value) {
23511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        bool old = unchecked_call;
23611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        unchecked_call = false;
23711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return old && id == return_value && &id == &return_value;
23811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
23911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert};
24011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
24111cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <class T, T* Ptr> int   FunctionPtrID<T, Ptr>::dummy = 0;
24211cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <class T, T* Ptr> void* FunctionPtrID<T, Ptr>::id = (void*)&FunctionPtrID<T, Ptr>::dummy;
24311cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <class T, T* Ptr> bool  FunctionPtrID<T, Ptr>::unchecked_call = false;
24411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
24511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//==============================================================================
24611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// BasicTest - The basic test structure for everything except
24711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// member object pointers.
24811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// ID - The "Function Identifier" type used either MethodID or FunctionPtrID.
24911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Arity - The Arity of the call signature.
25011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// ObjectCaster - The object transformation functor type.
25111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// ArgCaster - The extra argument transformation functor type.
25211cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <class ID, int Arity, class ObjectCaster = LValueCaster,
25311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                               class ArgCaster    = LValueCaster>
25411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstruct BasicTest {
25511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    template <class ObjectT>
25611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    void runTest(ObjectT& object) {
25711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        Int<Arity> A;
25811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        runTestImp(A, object);
25911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
26011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
26111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    template <class MethodPtr, class ObjectT>
26211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    void runTest(MethodPtr ptr, ObjectT& object) {
26311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        Int<Arity> A;
26411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        runTestImp(A, ptr, object);
26511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
26611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
26711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertprivate:
26811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    typedef void*& CallRet;
26911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    ObjectCaster object_cast;
27011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    ArgCaster arg_cast;
27111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    ArgType a0, a1, a2;
27211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
27311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    //==========================================================================
27411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    //                       BULLET 1, 2 AND 3 TEST METHODS
27511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    //==========================================================================
27611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    template <class MethodPtr, class ObjectT>
27711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    void runTestImp(Int<0>, MethodPtr ptr, ObjectT& object) {
27811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        {
27911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            static_assert((std::is_same<
28011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                decltype(std::__invoke(ptr, object_cast(object)))
28111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              , CallRet>::value), "");
28211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            assert(ID::unchecked_call == false);
28311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            CallRet ret = std::__invoke(ptr, object_cast(object));
28411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            assert(ID::checkCalled(ret));
28511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
28611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if TEST_STD_VER >= 11
28711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        {
28811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            static_assert((std::is_same<
28911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                decltype(std::__invoke_constexpr(ptr, object_cast(object)))
29011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              , CallRet>::value), "");
29111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            assert(ID::unchecked_call == false);
29211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            CallRet ret = std::__invoke_constexpr(ptr, object_cast(object));
29311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            assert(ID::checkCalled(ret));
29411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
29511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif
29611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
29711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
29811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    template <class MethodPtr, class ObjectT>
29911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    void runTestImp(Int<1>, MethodPtr ptr, ObjectT& object) {
30011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        {
30111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            static_assert((std::is_same<
30211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                decltype(std::__invoke(ptr, object_cast(object), arg_cast(a0)))
30311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              , CallRet>::value), "");
30411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            assert(ID::unchecked_call == false);
30511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            CallRet ret = std::__invoke(ptr, object_cast(object), arg_cast(a0));
30611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            assert(ID::checkCalled(ret));
30711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
30811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if TEST_STD_VER >= 11
30911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        {
31011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            static_assert((std::is_same<
31111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                decltype(std::__invoke_constexpr(ptr, object_cast(object), arg_cast(a0)))
31211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              , CallRet>::value), "");
31311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            assert(ID::unchecked_call == false);
31411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            CallRet ret = std::__invoke_constexpr(ptr, object_cast(object), arg_cast(a0));
31511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            assert(ID::checkCalled(ret));
31611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
31711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif
31811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
31911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
32011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    template <class MethodPtr, class ObjectT>
32111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    void runTestImp(Int<2>, MethodPtr ptr, ObjectT& object) {
32211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        {
32311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            static_assert((std::is_same<
32411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                decltype(std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1)))
32511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              , CallRet>::value), "");
32611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            assert(ID::unchecked_call == false);
32711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            CallRet ret = std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1));
32811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            assert(ID::checkCalled(ret));
32911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
33011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if TEST_STD_VER >= 11
33111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        {
33211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            static_assert((std::is_same<
33311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                decltype(std::__invoke_constexpr(ptr, object_cast(object), arg_cast(a0), arg_cast(a1)))
33411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              , CallRet>::value), "");
33511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            assert(ID::unchecked_call == false);
33611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            CallRet ret = std::__invoke_constexpr(ptr, object_cast(object), arg_cast(a0), arg_cast(a1));
33711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            assert(ID::checkCalled(ret));
33811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
33911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif
34011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
34111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
34211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    template <class MethodPtr, class ObjectT>
34311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    void runTestImp(Int<3>, MethodPtr ptr, ObjectT& object) {
34411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        {
34511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            static_assert((std::is_same<
34611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                decltype(std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2)))
34711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              , CallRet>::value), "");
34811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            assert(ID::unchecked_call == false);
34911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            CallRet ret = std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2));
35011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            assert(ID::checkCalled(ret));
35111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
35211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if TEST_STD_VER >= 11
35311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        {
35411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            static_assert((std::is_same<
35511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                decltype(std::__invoke_constexpr(ptr, object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2)))
35611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              , CallRet>::value), "");
35711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            assert(ID::unchecked_call == false);
35811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            CallRet ret = std::__invoke_constexpr(ptr, object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2));
35911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            assert(ID::checkCalled(ret));
36011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
36111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif
36211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
36311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
36411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    //==========================================================================
36511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    //                       BULLET 7 TEST METHODS
36611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    //==========================================================================
36711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    template <class ObjectT>
36811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    void runTestImp(Int<0>, ObjectT& object) {
36911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        {
37011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            static_assert((std::is_same<
37111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                decltype(std::__invoke(object_cast(object)))
37211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              , CallRet>::value), "");
37311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            assert(ID::unchecked_call == false);
37411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            CallRet ret = std::__invoke(object_cast(object));
37511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            assert(ID::checkCalled(ret));
37611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
37711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if TEST_STD_VER >= 11
37811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        {
37911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            static_assert((std::is_same<
38011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                decltype(std::__invoke_constexpr(object_cast(object)))
38111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              , CallRet>::value), "");
38211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            assert(ID::unchecked_call == false);
38311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            CallRet ret = std::__invoke_constexpr(object_cast(object));
38411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            assert(ID::checkCalled(ret));
38511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
38611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif
38711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
38811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
38911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    template <class ObjectT>
39011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    void runTestImp(Int<1>, ObjectT& object) {
39111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        {
39211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            static_assert((std::is_same<
39311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                decltype(std::__invoke(object_cast(object), arg_cast(a0)))
39411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              , CallRet>::value), "");
39511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            assert(ID::unchecked_call == false);
39611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            CallRet ret = std::__invoke(object_cast(object), arg_cast(a0));
39711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            assert(ID::checkCalled(ret));
39811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
39911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if TEST_STD_VER >= 11
40011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        {
40111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            static_assert((std::is_same<
40211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                decltype(std::__invoke_constexpr(object_cast(object), arg_cast(a0)))
40311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              , CallRet>::value), "");
40411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            assert(ID::unchecked_call == false);
40511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            CallRet ret = std::__invoke_constexpr(object_cast(object), arg_cast(a0));
40611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            assert(ID::checkCalled(ret));
40711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
40811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif
40911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
41011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
41111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    template <class ObjectT>
41211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    void runTestImp(Int<2>, ObjectT& object) {
41311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        {
41411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            static_assert((std::is_same<
41511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                decltype(std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1)))
41611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              , CallRet>::value), "");
41711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            assert(ID::unchecked_call == false);
41811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            CallRet ret = std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1));
41911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            assert(ID::checkCalled(ret));
42011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
42111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if TEST_STD_VER >= 11
42211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        {
42311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            static_assert((std::is_same<
42411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                decltype(std::__invoke_constexpr(object_cast(object), arg_cast(a0), arg_cast(a1)))
42511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              , CallRet>::value), "");
42611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            assert(ID::unchecked_call == false);
42711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            CallRet ret = std::__invoke_constexpr(object_cast(object), arg_cast(a0), arg_cast(a1));
42811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            assert(ID::checkCalled(ret));
42911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
43011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif
43111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
43211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
43311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    template <class ObjectT>
43411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    void runTestImp(Int<3>, ObjectT& object) {
43511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        {
43611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            static_assert((std::is_same<
43711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                decltype(std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2)))
43811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              , CallRet>::value), "");
43911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            assert(ID::unchecked_call == false);
44011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            CallRet ret = std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2));
44111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            assert(ID::checkCalled(ret));
44211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
44311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if TEST_STD_VER >= 11
44411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        {
44511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            static_assert((std::is_same<
44611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                decltype(std::__invoke_constexpr(object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2)))
44711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              , CallRet>::value), "");
44811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            assert(ID::unchecked_call == false);
44911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            CallRet ret = std::__invoke_constexpr(object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2));
45011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            assert(ID::checkCalled(ret));
45111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
45211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif
45311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
45411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert};
45511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
45611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif // INVOKE_HELPERS_H
457