Home | History | Annotate | Download | only in tuple.cnstr
      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 // <tuple>
     11 
     12 // template <class... Types> class tuple;
     13 
     14 // template <class... UTypes>
     15 //   explicit tuple(UTypes&&... u);
     16 
     17 // UNSUPPORTED: c++98, c++03
     18 
     19 #include <tuple>
     20 #include <cassert>
     21 #include <type_traits>
     22 
     23 #include "MoveOnly.h"
     24 
     25 #if _LIBCPP_STD_VER > 11
     26 
     27 struct Empty {};
     28 struct A
     29 {
     30     int id_;
     31     explicit constexpr A(int i) : id_(i) {}
     32 };
     33 
     34 #endif
     35 
     36 struct NoDefault { NoDefault() = delete; };
     37 
     38 // Make sure the _Up... constructor SFINAEs out when the types that
     39 // are not explicitly initialized are not all default constructible.
     40 // Otherwise, std::is_constructible would return true but instantiating
     41 // the constructor would fail.
     42 void test_default_constructible_extension_sfinae()
     43 {
     44     {
     45         typedef std::tuple<MoveOnly, NoDefault> Tuple;
     46 
     47         static_assert(!std::is_constructible<
     48             Tuple,
     49             MoveOnly
     50         >::value, "");
     51 
     52         static_assert(std::is_constructible<
     53             Tuple,
     54             MoveOnly, NoDefault
     55         >::value, "");
     56     }
     57     {
     58         typedef std::tuple<MoveOnly, MoveOnly, NoDefault> Tuple;
     59 
     60         static_assert(!std::is_constructible<
     61             Tuple,
     62             MoveOnly, MoveOnly
     63         >::value, "");
     64 
     65         static_assert(std::is_constructible<
     66             Tuple,
     67             MoveOnly, MoveOnly, NoDefault
     68         >::value, "");
     69     }
     70     {
     71         // Same idea as above but with a nested tuple type.
     72         typedef std::tuple<MoveOnly, NoDefault> Tuple;
     73         typedef std::tuple<MoveOnly, Tuple, MoveOnly, MoveOnly> NestedTuple;
     74 
     75         static_assert(!std::is_constructible<
     76             NestedTuple,
     77             MoveOnly, MoveOnly, MoveOnly, MoveOnly
     78         >::value, "");
     79 
     80         static_assert(std::is_constructible<
     81             NestedTuple,
     82             MoveOnly, Tuple, MoveOnly, MoveOnly
     83         >::value, "");
     84     }
     85     {
     86         typedef std::tuple<MoveOnly, int> Tuple;
     87         typedef std::tuple<MoveOnly, Tuple, MoveOnly, MoveOnly> NestedTuple;
     88 
     89         static_assert(std::is_constructible<
     90             NestedTuple,
     91             MoveOnly, MoveOnly, MoveOnly, MoveOnly
     92         >::value, "");
     93 
     94         static_assert(std::is_constructible<
     95             NestedTuple,
     96             MoveOnly, Tuple, MoveOnly, MoveOnly
     97         >::value, "");
     98     }
     99 }
    100 
    101 int main()
    102 {
    103     {
    104         std::tuple<MoveOnly> t(MoveOnly(0));
    105         assert(std::get<0>(t) == 0);
    106     }
    107     {
    108         std::tuple<MoveOnly, MoveOnly> t(MoveOnly(0), MoveOnly(1));
    109         assert(std::get<0>(t) == 0);
    110         assert(std::get<1>(t) == 1);
    111     }
    112     {
    113         std::tuple<MoveOnly, MoveOnly, MoveOnly> t(MoveOnly(0),
    114                                                    MoveOnly(1),
    115                                                    MoveOnly(2));
    116         assert(std::get<0>(t) == 0);
    117         assert(std::get<1>(t) == 1);
    118         assert(std::get<2>(t) == 2);
    119     }
    120     // extensions
    121     {
    122         std::tuple<MoveOnly, MoveOnly, MoveOnly> t(MoveOnly(0),
    123                                                    MoveOnly(1));
    124         assert(std::get<0>(t) == 0);
    125         assert(std::get<1>(t) == 1);
    126         assert(std::get<2>(t) == MoveOnly());
    127     }
    128     {
    129         std::tuple<MoveOnly, MoveOnly, MoveOnly> t(MoveOnly(0));
    130         assert(std::get<0>(t) == 0);
    131         assert(std::get<1>(t) == MoveOnly());
    132         assert(std::get<2>(t) == MoveOnly());
    133     }
    134 #if _LIBCPP_STD_VER > 11
    135     {
    136         constexpr std::tuple<Empty> t0{Empty()};
    137     }
    138     {
    139         constexpr std::tuple<A, A> t(3, 2);
    140         static_assert(std::get<0>(t).id_ == 3, "");
    141     }
    142 #endif
    143     // Check that SFINAE is properly applied with the default reduced arity
    144     // constructor extensions.
    145     test_default_constructible_extension_sfinae();
    146 }
    147