libcxx

libcxx mirror with random patches
git clone https://git.neptards.moe/neptards/libcxx.git
Log | Files | Refs

invoke.pass.cpp (13665B)


      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 <utility> // for std::move
     44 #include <cassert>
     45 
     46 struct NonCopyable {
     47     NonCopyable() {}
     48 private:
     49     NonCopyable(NonCopyable const&) = delete;
     50     NonCopyable& operator=(NonCopyable const&) = delete;
     51 };
     52 
     53 struct TestClass {
     54     explicit TestClass(int x) : data(x) {}
     55 
     56     int& operator()(NonCopyable&&) & { return data; }
     57     int const& operator()(NonCopyable&&) const & { return data; }
     58     int volatile& operator()(NonCopyable&&) volatile & { return data; }
     59     int const volatile& operator()(NonCopyable&&) const volatile & { return data; }
     60 
     61     int&& operator()(NonCopyable&&) && { return std::move(data); }
     62     int const&& operator()(NonCopyable&&) const && { return std::move(data); }
     63     int volatile&& operator()(NonCopyable&&) volatile && { return std::move(data); }
     64     int const volatile&& operator()(NonCopyable&&) const volatile && { return std::move(data); }
     65 
     66     int data;
     67 private:
     68     TestClass(TestClass const&) = delete;
     69     TestClass& operator=(TestClass const&) = delete;
     70 };
     71 
     72 struct DerivedFromTestClass : public TestClass {
     73     explicit DerivedFromTestClass(int x) : TestClass(x) {}
     74 };
     75 
     76 int& foo(NonCopyable&&) {
     77     static int data = 42;
     78     return data;
     79 }
     80 
     81 template <class Signature,  class Expect, class Functor>
     82 void test_b12(Functor&& f) {
     83     // Create the callable object.
     84     typedef Signature TestClass::*ClassFunc;
     85     ClassFunc func_ptr = &TestClass::operator();
     86 
     87     // Create the dummy arg.
     88     NonCopyable arg;
     89 
     90     // Check that the deduced return type of invoke is what is expected.
     91     typedef decltype(
     92         std::invoke(func_ptr, std::forward<Functor>(f), std::move(arg))
     93     ) DeducedReturnType;
     94     static_assert((std::is_same<DeducedReturnType, Expect>::value), "");
     95 
     96     // Check that result_of_t matches Expect.
     97     typedef typename std::result_of<ClassFunc&&(Functor&&, NonCopyable&&)>::type
     98       ResultOfReturnType;
     99     static_assert((std::is_same<ResultOfReturnType, Expect>::value), "");
    100 
    101     // Run invoke and check the return value.
    102     DeducedReturnType ret =
    103             std::invoke(func_ptr, std::forward<Functor>(f), std::move(arg));
    104     assert(ret == 42);
    105 }
    106 
    107 template <class Expect, class Functor>
    108 void test_b34(Functor&& f) {
    109     // Create the callable object.
    110     typedef int TestClass::*ClassFunc;
    111     ClassFunc func_ptr = &TestClass::data;
    112 
    113     // Check that the deduced return type of invoke is what is expected.
    114     typedef decltype(
    115         std::invoke(func_ptr, std::forward<Functor>(f))
    116     ) DeducedReturnType;
    117     static_assert((std::is_same<DeducedReturnType, Expect>::value), "");
    118 
    119     // Check that result_of_t matches Expect.
    120     typedef typename std::result_of<ClassFunc&&(Functor&&)>::type
    121             ResultOfReturnType;
    122     static_assert((std::is_same<ResultOfReturnType, Expect>::value), "");
    123 
    124     // Run invoke and check the return value.
    125     DeducedReturnType ret =
    126             std::invoke(func_ptr, std::forward<Functor>(f));
    127     assert(ret == 42);
    128 }
    129 
    130 template <class Expect, class Functor>
    131 void test_b5(Functor&& f) {
    132     NonCopyable arg;
    133 
    134     // Check that the deduced return type of invoke is what is expected.
    135     typedef decltype(
    136         std::invoke(std::forward<Functor>(f), std::move(arg))
    137     ) DeducedReturnType;
    138     static_assert((std::is_same<DeducedReturnType, Expect>::value), "");
    139 
    140     // Check that result_of_t matches Expect.
    141     typedef typename std::result_of<Functor&&(NonCopyable&&)>::type
    142             ResultOfReturnType;
    143     static_assert((std::is_same<ResultOfReturnType, Expect>::value), "");
    144 
    145     // Run invoke and check the return value.
    146     DeducedReturnType ret = std::invoke(std::forward<Functor>(f), std::move(arg));
    147     assert(ret == 42);
    148 }
    149 
    150 void bullet_one_two_tests() {
    151     {
    152         TestClass cl(42);
    153         test_b12<int&(NonCopyable&&) &, int&>(cl);
    154         test_b12<int const&(NonCopyable&&) const &, int const&>(cl);
    155         test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl);
    156         test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl);
    157 
    158         test_b12<int&&(NonCopyable&&) &&, int&&>(std::move(cl));
    159         test_b12<int const&&(NonCopyable&&) const &&, int const&&>(std::move(cl));
    160         test_b12<int volatile&&(NonCopyable&&) volatile &&, int volatile&&>(std::move(cl));
    161         test_b12<int const volatile&&(NonCopyable&&) const volatile &&, int const volatile&&>(std::move(cl));
    162     }
    163     {
    164         DerivedFromTestClass cl(42);
    165         test_b12<int&(NonCopyable&&) &, int&>(cl);
    166         test_b12<int const&(NonCopyable&&) const &, int const&>(cl);
    167         test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl);
    168         test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl);
    169 
    170         test_b12<int&&(NonCopyable&&) &&, int&&>(std::move(cl));
    171         test_b12<int const&&(NonCopyable&&) const &&, int const&&>(std::move(cl));
    172         test_b12<int volatile&&(NonCopyable&&) volatile &&, int volatile&&>(std::move(cl));
    173         test_b12<int const volatile&&(NonCopyable&&) const volatile &&, int const volatile&&>(std::move(cl));
    174     }
    175     {
    176         TestClass cl_obj(42);
    177         std::reference_wrapper<TestClass> cl(cl_obj);
    178         test_b12<int&(NonCopyable&&) &, int&>(cl);
    179         test_b12<int const&(NonCopyable&&) const &, int const&>(cl);
    180         test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl);
    181         test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl);
    182 
    183         test_b12<int&(NonCopyable&&) &, int&>(std::move(cl));
    184         test_b12<int const&(NonCopyable&&) const &, int const&>(std::move(cl));
    185         test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(std::move(cl));
    186         test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(std::move(cl));
    187     }
    188     {
    189         DerivedFromTestClass cl_obj(42);
    190         std::reference_wrapper<DerivedFromTestClass> cl(cl_obj);
    191         test_b12<int&(NonCopyable&&) &, int&>(cl);
    192         test_b12<int const&(NonCopyable&&) const &, int const&>(cl);
    193         test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl);
    194         test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl);
    195 
    196         test_b12<int&(NonCopyable&&) &, int&>(std::move(cl));
    197         test_b12<int const&(NonCopyable&&) const &, int const&>(std::move(cl));
    198         test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(std::move(cl));
    199         test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(std::move(cl));
    200     }
    201     {
    202         TestClass cl_obj(42);
    203         TestClass *cl = &cl_obj;
    204         test_b12<int&(NonCopyable&&) &, int&>(cl);
    205         test_b12<int const&(NonCopyable&&) const &, int const&>(cl);
    206         test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl);
    207         test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl);
    208     }
    209     {
    210         DerivedFromTestClass cl_obj(42);
    211         DerivedFromTestClass *cl = &cl_obj;
    212         test_b12<int&(NonCopyable&&) &, int&>(cl);
    213         test_b12<int const&(NonCopyable&&) const &, int const&>(cl);
    214         test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl);
    215         test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl);
    216     }
    217 }
    218 
    219 void bullet_three_four_tests() {
    220     {
    221         typedef TestClass Fn;
    222         Fn cl(42);
    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         test_b34<int&&>(static_cast<Fn &&>(cl));
    229         test_b34<int const&&>(static_cast<Fn const&&>(cl));
    230         test_b34<int volatile&&>(static_cast<Fn volatile&&>(cl));
    231         test_b34<int const volatile&&>(static_cast<Fn const volatile&&>(cl));
    232     }
    233     {
    234         typedef DerivedFromTestClass Fn;
    235         Fn cl(42);
    236         test_b34<int&>(cl);
    237         test_b34<int const&>(static_cast<Fn const&>(cl));
    238         test_b34<int volatile&>(static_cast<Fn volatile&>(cl));
    239         test_b34<int const volatile&>(static_cast<Fn const volatile &>(cl));
    240 
    241         test_b34<int&&>(static_cast<Fn &&>(cl));
    242         test_b34<int const&&>(static_cast<Fn const&&>(cl));
    243         test_b34<int volatile&&>(static_cast<Fn volatile&&>(cl));
    244         test_b34<int const volatile&&>(static_cast<Fn const volatile&&>(cl));
    245     }
    246     {
    247         typedef TestClass Fn;
    248         Fn cl(42);
    249         test_b34<int&>(std::reference_wrapper<Fn>(cl));
    250         test_b34<int const&>(std::reference_wrapper<Fn const>(cl));
    251         test_b34<int volatile&>(std::reference_wrapper<Fn volatile>(cl));
    252         test_b34<int const volatile&>(std::reference_wrapper<Fn const volatile>(cl));
    253     }
    254     {
    255         typedef DerivedFromTestClass Fn;
    256         Fn cl(42);
    257         test_b34<int&>(std::reference_wrapper<Fn>(cl));
    258         test_b34<int const&>(std::reference_wrapper<Fn const>(cl));
    259         test_b34<int volatile&>(std::reference_wrapper<Fn volatile>(cl));
    260         test_b34<int const volatile&>(std::reference_wrapper<Fn const volatile>(cl));
    261     }
    262     {
    263         typedef TestClass Fn;
    264         Fn cl_obj(42);
    265         Fn* cl = &cl_obj;
    266         test_b34<int&>(cl);
    267         test_b34<int const&>(static_cast<Fn const*>(cl));
    268         test_b34<int volatile&>(static_cast<Fn volatile*>(cl));
    269         test_b34<int const volatile&>(static_cast<Fn const volatile *>(cl));
    270     }
    271     {
    272         typedef DerivedFromTestClass Fn;
    273         Fn cl_obj(42);
    274         Fn* cl = &cl_obj;
    275         test_b34<int&>(cl);
    276         test_b34<int const&>(static_cast<Fn const*>(cl));
    277         test_b34<int volatile&>(static_cast<Fn volatile*>(cl));
    278         test_b34<int const volatile&>(static_cast<Fn const volatile *>(cl));
    279     }
    280 }
    281 
    282 void bullet_five_tests() {
    283     using FooType = int&(NonCopyable&&);
    284     {
    285         FooType& fn = foo;
    286         test_b5<int &>(fn);
    287     }
    288     {
    289         FooType* fn = foo;
    290         test_b5<int &>(fn);
    291     }
    292     {
    293         typedef TestClass Fn;
    294         Fn cl(42);
    295         test_b5<int&>(cl);
    296         test_b5<int const&>(static_cast<Fn const&>(cl));
    297         test_b5<int volatile&>(static_cast<Fn volatile&>(cl));
    298         test_b5<int const volatile&>(static_cast<Fn const volatile &>(cl));
    299 
    300         test_b5<int&&>(static_cast<Fn &&>(cl));
    301         test_b5<int const&&>(static_cast<Fn const&&>(cl));
    302         test_b5<int volatile&&>(static_cast<Fn volatile&&>(cl));
    303         test_b5<int const volatile&&>(static_cast<Fn const volatile&&>(cl));
    304     }
    305 }
    306 
    307 struct CopyThrows {
    308   CopyThrows() {}
    309   CopyThrows(CopyThrows const&) {}
    310   CopyThrows(CopyThrows&&) noexcept {}
    311 };
    312 
    313 struct NoThrowCallable {
    314   void operator()() noexcept {}
    315   void operator()(CopyThrows) noexcept {}
    316 };
    317 
    318 struct ThrowsCallable {
    319   void operator()() {}
    320 };
    321 
    322 struct MemberObj {
    323   int x;
    324 };
    325 
    326 void noexcept_test() {
    327     {
    328         NoThrowCallable obj; ((void)obj); // suppress unused warning
    329         CopyThrows arg; ((void)arg); // suppress unused warning
    330         static_assert(noexcept(std::invoke(obj)), "");
    331         static_assert(!noexcept(std::invoke(obj, arg)), "");
    332         static_assert(noexcept(std::invoke(obj, std::move(arg))), "");
    333     }
    334     {
    335         ThrowsCallable obj; ((void)obj); // suppress unused warning
    336         static_assert(!noexcept(std::invoke(obj)), "");
    337     }
    338     {
    339         MemberObj obj{42}; ((void)obj); // suppress unused warning.
    340         static_assert(noexcept(std::invoke(&MemberObj::x, obj)), "");
    341     }
    342 }
    343 
    344 int main() {
    345     bullet_one_two_tests();
    346     bullet_three_four_tests();
    347     bullet_five_tests();
    348     noexcept_test();
    349 }