Home | History | Annotate | Download | only in tuple.apply
      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
     11 
     12 // <experimental/tuple>
     13 
     14 // template <class F, class T> constexpr decltype(auto) apply(F &&, T &&)
     15 
     16 // Testing extended function types. The extended function types are those
     17 // named by INVOKE but that are not actual callable objects. These include
     18 // bullets 1-4 of invoke.
     19 
     20 #include <experimental/tuple>
     21 #include <array>
     22 #include <utility>
     23 #include <cassert>
     24 
     25 // std::array is explicitly allowed to be initialized with A a = { init-list };.
     26 // Disable the missing braces warning for this reason.
     27 #include "disable_missing_braces_warning.h"
     28 
     29 int count = 0;
     30 
     31 struct A_int_0
     32 {
     33     A_int_0() : obj1(0){}
     34     A_int_0(int x) : obj1(x) {}
     35     int mem1() { return ++count; }
     36     int mem2() const { return ++count; }
     37     int const obj1;
     38 };
     39 
     40 struct A_int_1
     41 {
     42     A_int_1() {}
     43     A_int_1(int) {}
     44     int mem1(int x) { return count += x; }
     45     int mem2(int x) const { return count += x; }
     46 };
     47 
     48 struct A_int_2
     49 {
     50     A_int_2() {}
     51     A_int_2(int) {}
     52     int mem1(int x, int y) { return count += (x + y); }
     53     int mem2(int x, int y) const { return count += (x + y); }
     54 };
     55 
     56 template <class A>
     57 struct A_wrap
     58 {
     59     A_wrap() {}
     60     A_wrap(int x) : m_a(x) {}
     61     A & operator*() { return m_a; }
     62     A const & operator*() const { return m_a; }
     63     A m_a;
     64 };
     65 
     66 typedef A_wrap<A_int_0> A_wrap_0;
     67 typedef A_wrap<A_int_1> A_wrap_1;
     68 typedef A_wrap<A_int_2> A_wrap_2;
     69 
     70 
     71 template <class A>
     72 struct A_base : public A
     73 {
     74     A_base() : A() {}
     75     A_base(int x) : A(x) {}
     76 };
     77 
     78 typedef A_base<A_int_0> A_base_0;
     79 typedef A_base<A_int_1> A_base_1;
     80 typedef A_base<A_int_2> A_base_2;
     81 
     82 namespace ex = std::experimental;
     83 
     84 template <
     85     class Tuple, class ConstTuple
     86   , class TuplePtr, class ConstTuplePtr
     87   , class TupleWrap, class ConstTupleWrap
     88   , class TupleBase, class ConstTupleBase
     89   >
     90 void test_ext_int_0()
     91 {
     92     count = 0;
     93     typedef A_int_0 T;
     94     typedef A_wrap_0 Wrap;
     95     typedef A_base_0 Base;
     96 
     97     typedef int(T::*mem1_t)();
     98     mem1_t mem1 = &T::mem1;
     99 
    100     typedef int(T::*mem2_t)() const;
    101     mem2_t mem2 = &T::mem2;
    102 
    103     typedef int const T::*obj1_t;
    104     obj1_t obj1 = &T::obj1;
    105 
    106     // member function w/ref
    107     {
    108         T a;
    109         Tuple t{a};
    110         assert(1 == ex::apply(mem1, t));
    111         assert(count == 1);
    112     }
    113     count = 0;
    114     // member function w/pointer
    115     {
    116         T a;
    117         TuplePtr t{&a};
    118         assert(1 == ex::apply(mem1, t));
    119         assert(count == 1);
    120     }
    121     count = 0;
    122     // member function w/base
    123     {
    124         Base a;
    125         TupleBase t{a};
    126         assert(1 == ex::apply(mem1, t));
    127         assert(count == 1);
    128     }
    129     count = 0;
    130     // member function w/wrap
    131     {
    132         Wrap a;
    133         TupleWrap t{a};
    134         assert(1 == ex::apply(mem1, t));
    135         assert(count == 1);
    136     }
    137     count = 0;
    138     // const member function w/ref
    139     {
    140         T const a;
    141         ConstTuple t{a};
    142         assert(1 == ex::apply(mem2, t));
    143         assert(count == 1);
    144     }
    145     count = 0;
    146     // const member function w/pointer
    147     {
    148         T const a;
    149         ConstTuplePtr t{&a};
    150         assert(1 == ex::apply(mem2, t));
    151         assert(count == 1);
    152     }
    153     count = 0;
    154     // const member function w/base
    155     {
    156         Base const a;
    157         ConstTupleBase t{a};
    158         assert(1 == ex::apply(mem2, t));
    159         assert(count == 1);
    160     }
    161     count = 0;
    162     // const member function w/wrapper
    163     {
    164         Wrap const a;
    165         ConstTupleWrap t{a};
    166         assert(1 == ex::apply(mem2, t));
    167         assert(1 == count);
    168     }
    169     // member object w/ref
    170     {
    171         T a{42};
    172         Tuple t{a};
    173         assert(42 == ex::apply(obj1, t));
    174     }
    175     // member object w/pointer
    176     {
    177         T a{42};
    178         TuplePtr t{&a};
    179         assert(42 == ex::apply(obj1, t));
    180     }
    181     // member object w/base
    182     {
    183         Base a{42};
    184         TupleBase t{a};
    185         assert(42 == ex::apply(obj1, t));
    186     }
    187     // member object w/wrapper
    188     {
    189         Wrap a{42};
    190         TupleWrap t{a};
    191         assert(42 == ex::apply(obj1, t));
    192     }
    193 }
    194 
    195 
    196 template <
    197     class Tuple, class ConstTuple
    198   , class TuplePtr, class ConstTuplePtr
    199   , class TupleWrap, class ConstTupleWrap
    200   , class TupleBase, class ConstTupleBase
    201   >
    202 void test_ext_int_1()
    203 {
    204     count = 0;
    205     typedef A_int_1 T;
    206     typedef A_wrap_1 Wrap;
    207     typedef A_base_1 Base;
    208 
    209     typedef int(T::*mem1_t)(int);
    210     mem1_t mem1 = &T::mem1;
    211 
    212     typedef int(T::*mem2_t)(int) const;
    213     mem2_t mem2 = &T::mem2;
    214 
    215     // member function w/ref
    216     {
    217         T a;
    218         Tuple t{a, 2};
    219         assert(2 == ex::apply(mem1, t));
    220         assert(count == 2);
    221     }
    222     count = 0;
    223     // member function w/pointer
    224     {
    225         T a;
    226         TuplePtr t{&a, 3};
    227         assert(3 == ex::apply(mem1, t));
    228         assert(count == 3);
    229     }
    230     count = 0;
    231     // member function w/base
    232     {
    233         Base a;
    234         TupleBase t{a, 4};
    235         assert(4 == ex::apply(mem1, t));
    236         assert(count == 4);
    237     }
    238     count = 0;
    239     // member function w/wrap
    240     {
    241         Wrap a;
    242         TupleWrap t{a, 5};
    243         assert(5 == ex::apply(mem1, t));
    244         assert(count == 5);
    245     }
    246     count = 0;
    247     // const member function w/ref
    248     {
    249         T const a;
    250         ConstTuple t{a, 6};
    251         assert(6 == ex::apply(mem2, t));
    252         assert(count == 6);
    253     }
    254     count = 0;
    255     // const member function w/pointer
    256     {
    257         T const a;
    258         ConstTuplePtr t{&a, 7};
    259         assert(7 == ex::apply(mem2, t));
    260         assert(count == 7);
    261     }
    262     count = 0;
    263     // const member function w/base
    264     {
    265         Base const a;
    266         ConstTupleBase t{a, 8};
    267         assert(8 == ex::apply(mem2, t));
    268         assert(count == 8);
    269     }
    270     count = 0;
    271     // const member function w/wrapper
    272     {
    273         Wrap const a;
    274         ConstTupleWrap t{a, 9};
    275         assert(9 == ex::apply(mem2, t));
    276         assert(9 == count);
    277     }
    278 }
    279 
    280 
    281 template <
    282     class Tuple, class ConstTuple
    283   , class TuplePtr, class ConstTuplePtr
    284   , class TupleWrap, class ConstTupleWrap
    285   , class TupleBase, class ConstTupleBase
    286   >
    287 void test_ext_int_2()
    288 {
    289     count = 0;
    290     typedef A_int_2 T;
    291     typedef A_wrap_2 Wrap;
    292     typedef A_base_2 Base;
    293 
    294     typedef int(T::*mem1_t)(int, int);
    295     mem1_t mem1 = &T::mem1;
    296 
    297     typedef int(T::*mem2_t)(int, int) const;
    298     mem2_t mem2 = &T::mem2;
    299 
    300     // member function w/ref
    301     {
    302         T a;
    303         Tuple t{a, 1, 1};
    304         assert(2 == ex::apply(mem1, t));
    305         assert(count == 2);
    306     }
    307     count = 0;
    308     // member function w/pointer
    309     {
    310         T a;
    311         TuplePtr t{&a, 1, 2};
    312         assert(3 == ex::apply(mem1, t));
    313         assert(count == 3);
    314     }
    315     count = 0;
    316     // member function w/base
    317     {
    318         Base a;
    319         TupleBase t{a, 2, 2};
    320         assert(4 == ex::apply(mem1, t));
    321         assert(count == 4);
    322     }
    323     count = 0;
    324     // member function w/wrap
    325     {
    326         Wrap a;
    327         TupleWrap t{a, 2, 3};
    328         assert(5 == ex::apply(mem1, t));
    329         assert(count == 5);
    330     }
    331     count = 0;
    332     // const member function w/ref
    333     {
    334         T const a;
    335         ConstTuple t{a, 3, 3};
    336         assert(6 == ex::apply(mem2, t));
    337         assert(count == 6);
    338     }
    339     count = 0;
    340     // const member function w/pointer
    341     {
    342         T const a;
    343         ConstTuplePtr t{&a, 3, 4};
    344         assert(7 == ex::apply(mem2, t));
    345         assert(count == 7);
    346     }
    347     count = 0;
    348     // const member function w/base
    349     {
    350         Base const a;
    351         ConstTupleBase t{a, 4, 4};
    352         assert(8 == ex::apply(mem2, t));
    353         assert(count == 8);
    354     }
    355     count = 0;
    356     // const member function w/wrapper
    357     {
    358         Wrap const a;
    359         ConstTupleWrap t{a, 4, 5};
    360         assert(9 == ex::apply(mem2, t));
    361         assert(9 == count);
    362     }
    363 }
    364 
    365 int main()
    366 {
    367     {
    368         test_ext_int_0<
    369             std::tuple<A_int_0 &>, std::tuple<A_int_0 const &>
    370           , std::tuple<A_int_0 *>, std::tuple<A_int_0 const *>
    371           , std::tuple<A_wrap_0 &>, std::tuple<A_wrap_0 const &>
    372           , std::tuple<A_base_0 &>, std::tuple<A_base_0 const &>
    373           >();
    374         test_ext_int_0<
    375             std::tuple<A_int_0>, std::tuple<A_int_0 const>
    376           , std::tuple<A_int_0 *>, std::tuple<A_int_0 const *>
    377           , std::tuple<A_wrap_0>, std::tuple<A_wrap_0 const>
    378           , std::tuple<A_base_0>, std::tuple<A_base_0 const>
    379           >();
    380         test_ext_int_0<
    381             std::array<A_int_0, 1>, std::array<A_int_0 const, 1>
    382           , std::array<A_int_0*, 1>, std::array<A_int_0 const*, 1>
    383           , std::array<A_wrap_0, 1>, std::array<A_wrap_0 const, 1>
    384           , std::array<A_base_0, 1>, std::array<A_base_0 const, 1>
    385           >();
    386     }
    387     {
    388         test_ext_int_1<
    389             std::tuple<A_int_1 &, int>, std::tuple<A_int_1 const &, int>
    390           , std::tuple<A_int_1 *, int>, std::tuple<A_int_1 const *, int>
    391           , std::tuple<A_wrap_1 &, int>, std::tuple<A_wrap_1 const &, int>
    392           , std::tuple<A_base_1 &, int>, std::tuple<A_base_1 const &, int>
    393           >();
    394         test_ext_int_1<
    395             std::tuple<A_int_1, int>, std::tuple<A_int_1 const, int>
    396           , std::tuple<A_int_1 *, int>, std::tuple<A_int_1 const *, int>
    397           , std::tuple<A_wrap_1, int>, std::tuple<A_wrap_1 const, int>
    398           , std::tuple<A_base_1, int>, std::tuple<A_base_1 const, int>
    399           >();
    400         test_ext_int_1<
    401             std::pair<A_int_1 &, int>, std::pair<A_int_1 const &, int>
    402           , std::pair<A_int_1 *, int>, std::pair<A_int_1 const *, int>
    403           , std::pair<A_wrap_1 &, int>, std::pair<A_wrap_1 const &, int>
    404           , std::pair<A_base_1 &, int>, std::pair<A_base_1 const &, int>
    405           >();
    406         test_ext_int_1<
    407             std::pair<A_int_1, int>, std::pair<A_int_1 const, int>
    408           , std::pair<A_int_1 *, int>, std::pair<A_int_1 const *, int>
    409           , std::pair<A_wrap_1, int>, std::pair<A_wrap_1 const, int>
    410           , std::pair<A_base_1, int>, std::pair<A_base_1 const, int>
    411           >();
    412     }
    413     {
    414         test_ext_int_2<
    415             std::tuple<A_int_2 &, int, int>, std::tuple<A_int_2 const &, int, int>
    416           , std::tuple<A_int_2 *, int, int>, std::tuple<A_int_2 const *, int, int>
    417           , std::tuple<A_wrap_2 &, int, int>, std::tuple<A_wrap_2 const &, int, int>
    418           , std::tuple<A_base_2 &, int, int>, std::tuple<A_base_2 const &, int, int>
    419           >();
    420         test_ext_int_2<
    421             std::tuple<A_int_2, int, int>, std::tuple<A_int_2 const, int, int>
    422           , std::tuple<A_int_2 *, int, int>, std::tuple<A_int_2 const *, int, int>
    423           , std::tuple<A_wrap_2, int, int>, std::tuple<A_wrap_2 const, int, int>
    424           , std::tuple<A_base_2, int, int>, std::tuple<A_base_2 const, int, int>
    425           >();
    426     }
    427 }
    428