Home | History | Annotate | Download | only in func.invoke
      1 //===----------------------------------------------------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is dual licensed under the MIT and the University of Illinois Open
      6 // Source Licenses. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 // UNSUPPORTED: c++98, c++03, c++11, c++14
     11 
     12 // <functional>
     13 
     14 // template <class F, class ...Args>
     15 // result_of_t<F&&(Args&&...)> invoke(F&&, Args&&...);
     16 
     17 /// C++14 [func.def] 20.9.0
     18 /// (1) The following definitions apply to this Clause:
     19 /// (2) A call signature is the name of a return type followed by a parenthesized
     20 ///     comma-separated list of zero or more argument types.
     21 /// (3) A callable type is a function object type (20.9) or a pointer to member.
     22 /// (4) A callable object is an object of a callable type.
     23 /// (5) A call wrapper type is a type that holds a callable object and supports
     24 ///     a call operation that forwards to that object.
     25 /// (6) A call wrapper is an object of a call wrapper type.
     26 /// (7) A target object is the callable object held by a call wrapper.
     27 
     28 /// C++14 [func.require] 20.9.1
     29 ///
     30 /// Define INVOKE (f, t1, t2, ..., tN) as follows:
     31 ///   (1.1) - (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is an object of
     32 ///   type T or a reference to an object of type T or a reference to an object of a type derived from T;
     33 ///   (1.2) - ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is not one of
     34 ///   the types described in the previous item;
     35 ///   (1.3) - t1.*f when N == 1 and f is a pointer to member data of a class T and t1 is an object of type T or a
     36 ///   reference to an object of type T or a reference to an object of a type derived from T;
     37 ///   (1.4) - (*t1).*f when N == 1 and f is a pointer to member data of a class T and t1 is not one of the types
     38 ///   described in the previous item;
     39 ///   (1.5) - f(t1, t2, ..., tN) in all other cases.
     40 
     41 #include <functional>
     42 #include <type_traits>
     43 #include <cassert>
     44 
     45 struct NonCopyable {
     46     NonCopyable() {}
     47 private:
     48     NonCopyable(NonCopyable const&) = delete;
     49     NonCopyable& operator=(NonCopyable const&) = delete;
     50 };
     51 
     52 struct TestClass {
     53     explicit TestClass(int x) : data(x) {}
     54 
     55     int& operator()(NonCopyable&&) & { return data; }
     56     int const& operator()(NonCopyable&&) const & { return data; }
     57     int volatile& operator()(NonCopyable&&) volatile & { return data; }
     58     int const volatile& operator()(NonCopyable&&) const volatile & { return data; }
     59 
     60     int&& operator()(NonCopyable&&) && { return std::move(data); }
     61     int const&& operator()(NonCopyable&&) const && { return std::move(data); }
     62     int volatile&& operator()(NonCopyable&&) volatile && { return std::move(data); }
     63     int const volatile&& operator()(NonCopyable&&) const volatile && { return std::move(data); }
     64 
     65     int data;
     66 private:
     67     TestClass(TestClass const&) = delete;
     68     TestClass& operator=(TestClass const&) = delete;
     69 };
     70 
     71 struct DerivedFromTestClass : public TestClass {
     72     explicit DerivedFromTestClass(int x) : TestClass(x) {}
     73 };
     74 
     75 int& foo(NonCopyable&&) {
     76     static int data = 42;
     77     return data;
     78 }
     79 
     80 template <class Signature,  class Expect, class Functor>
     81 void test_b12(Functor&& f) {
     82     // Create the callable object.
     83     typedef Signature TestClass::*ClassFunc;
     84     ClassFunc func_ptr = &TestClass::operator();
     85 
     86     // Create the dummy arg.
     87     NonCopyable arg;
     88 
     89     // Check that the deduced return type of invoke is what is expected.
     90     typedef decltype(
     91         std::invoke(func_ptr, std::forward<Functor>(f), std::move(arg))
     92     ) DeducedReturnType;
     93     static_assert((std::is_same<DeducedReturnType, Expect>::value), "");
     94 
     95     // Check that result_of_t matches Expect.
     96     typedef typename std::result_of<ClassFunc&&(Functor&&, NonCopyable&&)>::type
     97       ResultOfReturnType;
     98     static_assert((std::is_same<ResultOfReturnType, Expect>::value), "");
     99 
    100     // Run invoke and check the return value.
    101     DeducedReturnType ret =
    102             std::invoke(func_ptr, std::forward<Functor>(f), std::move(arg));
    103     assert(ret == 42);
    104 }
    105 
    106 template <class Expect, class Functor>
    107 void test_b34(Functor&& f) {
    108     // Create the callable object.
    109     typedef int TestClass::*ClassFunc;
    110     ClassFunc func_ptr = &TestClass::data;
    111 
    112     // Check that the deduced return type of invoke is what is expected.
    113     typedef decltype(
    114         std::invoke(func_ptr, std::forward<Functor>(f))
    115     ) DeducedReturnType;
    116     static_assert((std::is_same<DeducedReturnType, Expect>::value), "");
    117 
    118     // Check that result_of_t matches Expect.
    119     typedef typename std::result_of<ClassFunc&&(Functor&&)>::type
    120             ResultOfReturnType;
    121     static_assert((std::is_same<ResultOfReturnType, Expect>::value), "");
    122 
    123     // Run invoke and check the return value.
    124     DeducedReturnType ret =
    125             std::invoke(func_ptr, std::forward<Functor>(f));
    126     assert(ret == 42);
    127 }
    128 
    129 template <class Expect, class Functor>
    130 void test_b5(Functor&& f) {
    131     NonCopyable arg;
    132 
    133     // Check that the deduced return type of invoke is what is expected.
    134     typedef decltype(
    135         std::invoke(std::forward<Functor>(f), std::move(arg))
    136     ) DeducedReturnType;
    137     static_assert((std::is_same<DeducedReturnType, Expect>::value), "");
    138 
    139     // Check that result_of_t matches Expect.
    140     typedef typename std::result_of<Functor&&(NonCopyable&&)>::type
    141             ResultOfReturnType;
    142     static_assert((std::is_same<ResultOfReturnType, Expect>::value), "");
    143 
    144     // Run invoke and check the return value.
    145     DeducedReturnType ret = std::invoke(std::forward<Functor>(f), std::move(arg));
    146     assert(ret == 42);
    147 }
    148 
    149 void bullet_one_two_tests() {
    150     {
    151         TestClass cl(42);
    152         test_b12<int&(NonCopyable&&) &, int&>(cl);
    153         test_b12<int const&(NonCopyable&&) const &, int const&>(cl);
    154         test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl);
    155         test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl);
    156 
    157         test_b12<int&&(NonCopyable&&) &&, int&&>(std::move(cl));
    158         test_b12<int const&&(NonCopyable&&) const &&, int const&&>(std::move(cl));
    159         test_b12<int volatile&&(NonCopyable&&) volatile &&, int volatile&&>(std::move(cl));
    160         test_b12<int const volatile&&(NonCopyable&&) const volatile &&, int const volatile&&>(std::move(cl));
    161     }
    162     {
    163         DerivedFromTestClass cl(42);
    164         test_b12<int&(NonCopyable&&) &, int&>(cl);
    165         test_b12<int const&(NonCopyable&&) const &, int const&>(cl);
    166         test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl);
    167         test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl);
    168 
    169         test_b12<int&&(NonCopyable&&) &&, int&&>(std::move(cl));
    170         test_b12<int const&&(NonCopyable&&) const &&, int const&&>(std::move(cl));
    171         test_b12<int volatile&&(NonCopyable&&) volatile &&, int volatile&&>(std::move(cl));
    172         test_b12<int const volatile&&(NonCopyable&&) const volatile &&, int const volatile&&>(std::move(cl));
    173     }
    174     {
    175         TestClass cl_obj(42);
    176         TestClass *cl = &cl_obj;
    177         test_b12<int&(NonCopyable&&) &, int&>(cl);
    178         test_b12<int const&(NonCopyable&&) const &, int const&>(cl);
    179         test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl);
    180         test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl);
    181     }
    182     {
    183         DerivedFromTestClass cl_obj(42);
    184         DerivedFromTestClass *cl = &cl_obj;
    185         test_b12<int&(NonCopyable&&) &, int&>(cl);
    186         test_b12<int const&(NonCopyable&&) const &, int const&>(cl);
    187         test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl);
    188         test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl);
    189     }
    190 }
    191 
    192 void bullet_three_four_tests() {
    193     {
    194         typedef TestClass Fn;
    195         Fn cl(42);
    196         test_b34<int&>(cl);
    197         test_b34<int const&>(static_cast<Fn const&>(cl));
    198         test_b34<int volatile&>(static_cast<Fn volatile&>(cl));
    199         test_b34<int const volatile&>(static_cast<Fn const volatile &>(cl));
    200 
    201         test_b34<int&&>(static_cast<Fn &&>(cl));
    202         test_b34<int const&&>(static_cast<Fn const&&>(cl));
    203         test_b34<int volatile&&>(static_cast<Fn volatile&&>(cl));
    204         test_b34<int const volatile&&>(static_cast<Fn const volatile&&>(cl));
    205     }
    206     {
    207         typedef DerivedFromTestClass Fn;
    208         Fn cl(42);
    209         test_b34<int&>(cl);
    210         test_b34<int const&>(static_cast<Fn const&>(cl));
    211         test_b34<int volatile&>(static_cast<Fn volatile&>(cl));
    212         test_b34<int const volatile&>(static_cast<Fn const volatile &>(cl));
    213 
    214         test_b34<int&&>(static_cast<Fn &&>(cl));
    215         test_b34<int const&&>(static_cast<Fn const&&>(cl));
    216         test_b34<int volatile&&>(static_cast<Fn volatile&&>(cl));
    217         test_b34<int const volatile&&>(static_cast<Fn const volatile&&>(cl));
    218     }
    219     {
    220         typedef TestClass Fn;
    221         Fn cl_obj(42);
    222         Fn* cl = &cl_obj;
    223         test_b34<int&>(cl);
    224         test_b34<int const&>(static_cast<Fn const*>(cl));
    225         test_b34<int volatile&>(static_cast<Fn volatile*>(cl));
    226         test_b34<int const volatile&>(static_cast<Fn const volatile *>(cl));
    227     }
    228     {
    229         typedef DerivedFromTestClass Fn;
    230         Fn cl_obj(42);
    231         Fn* cl = &cl_obj;
    232         test_b34<int&>(cl);
    233         test_b34<int const&>(static_cast<Fn const*>(cl));
    234         test_b34<int volatile&>(static_cast<Fn volatile*>(cl));
    235         test_b34<int const volatile&>(static_cast<Fn const volatile *>(cl));
    236     }
    237 }
    238 
    239 void bullet_five_tests() {
    240     using FooType = int&(NonCopyable&&);
    241     {
    242         FooType& fn = foo;
    243         test_b5<int &>(fn);
    244     }
    245     {
    246         FooType* fn = foo;
    247         test_b5<int &>(fn);
    248     }
    249     {
    250         typedef TestClass Fn;
    251         Fn cl(42);
    252         test_b5<int&>(cl);
    253         test_b5<int const&>(static_cast<Fn const&>(cl));
    254         test_b5<int volatile&>(static_cast<Fn volatile&>(cl));
    255         test_b5<int const volatile&>(static_cast<Fn const volatile &>(cl));
    256 
    257         test_b5<int&&>(static_cast<Fn &&>(cl));
    258         test_b5<int const&&>(static_cast<Fn const&&>(cl));
    259         test_b5<int volatile&&>(static_cast<Fn volatile&&>(cl));
    260         test_b5<int const volatile&&>(static_cast<Fn const volatile&&>(cl));
    261     }
    262 }
    263 
    264 int main() {
    265     bullet_one_two_tests();
    266     bullet_three_four_tests();
    267     bullet_five_tests();
    268 }
    269