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 // tuple(tuple&& u);
     15 
     16 // UNSUPPORTED: c++98, c++03
     17 
     18 #include <tuple>
     19 #include <utility>
     20 #include <cassert>
     21 
     22 #include "MoveOnly.h"
     23 
     24 struct ConstructsWithTupleLeaf
     25 {
     26     ConstructsWithTupleLeaf() {}
     27 
     28     ConstructsWithTupleLeaf(ConstructsWithTupleLeaf const &) { assert(false); }
     29     ConstructsWithTupleLeaf(ConstructsWithTupleLeaf &&) {}
     30 
     31     template <class T>
     32     ConstructsWithTupleLeaf(T) {
     33         static_assert(!std::is_same<T, T>::value,
     34                       "Constructor instantiated for type other than int");
     35     }
     36 };
     37 
     38 // move_only type which triggers the empty base optimization
     39 struct move_only_ebo {
     40   move_only_ebo() = default;
     41   move_only_ebo(move_only_ebo&&) = default;
     42 };
     43 
     44 // a move_only type which does not trigger the empty base optimization
     45 struct move_only_large final {
     46   move_only_large() : value(42) {}
     47   move_only_large(move_only_large&&) = default;
     48   int value;
     49 };
     50 
     51 template <class Elem>
     52 void test_sfinae() {
     53     using Tup = std::tuple<Elem>;
     54     using Alloc = std::allocator<void>;
     55     using Tag = std::allocator_arg_t;
     56     // special members
     57     {
     58         static_assert(std::is_default_constructible<Tup>::value, "");
     59         static_assert(std::is_move_constructible<Tup>::value, "");
     60         static_assert(!std::is_copy_constructible<Tup>::value, "");
     61         static_assert(!std::is_constructible<Tup, Tup&>::value, "");
     62     }
     63     // args constructors
     64     {
     65         static_assert(std::is_constructible<Tup, Elem&&>::value, "");
     66         static_assert(!std::is_constructible<Tup, Elem const&>::value, "");
     67         static_assert(!std::is_constructible<Tup, Elem&>::value, "");
     68     }
     69     // uses-allocator special member constructors
     70     {
     71         static_assert(std::is_constructible<Tup, Tag, Alloc>::value, "");
     72         static_assert(std::is_constructible<Tup, Tag, Alloc, Tup&&>::value, "");
     73         static_assert(!std::is_constructible<Tup, Tag, Alloc, Tup const&>::value, "");
     74         static_assert(!std::is_constructible<Tup, Tag, Alloc, Tup &>::value, "");
     75     }
     76     // uses-allocator args constructors
     77     {
     78         static_assert(std::is_constructible<Tup, Tag, Alloc, Elem&&>::value, "");
     79         static_assert(!std::is_constructible<Tup, Tag, Alloc, Elem const&>::value, "");
     80         static_assert(!std::is_constructible<Tup, Tag, Alloc, Elem &>::value, "");
     81     }
     82 }
     83 
     84 int main()
     85 {
     86     {
     87         typedef std::tuple<> T;
     88         T t0;
     89         T t = std::move(t0);
     90         ((void)t); // Prevent unused warning
     91     }
     92     {
     93         typedef std::tuple<MoveOnly> T;
     94         T t0(MoveOnly(0));
     95         T t = std::move(t0);
     96         assert(std::get<0>(t) == 0);
     97     }
     98     {
     99         typedef std::tuple<MoveOnly, MoveOnly> T;
    100         T t0(MoveOnly(0), MoveOnly(1));
    101         T t = std::move(t0);
    102         assert(std::get<0>(t) == 0);
    103         assert(std::get<1>(t) == 1);
    104     }
    105     {
    106         typedef std::tuple<MoveOnly, MoveOnly, MoveOnly> T;
    107         T t0(MoveOnly(0), MoveOnly(1), MoveOnly(2));
    108         T t = std::move(t0);
    109         assert(std::get<0>(t) == 0);
    110         assert(std::get<1>(t) == 1);
    111         assert(std::get<2>(t) == 2);
    112     }
    113     // A bug in tuple caused __tuple_leaf to use its explicit converting constructor
    114     //  as its move constructor. This tests that ConstructsWithTupleLeaf is not called
    115     // (w/ __tuple_leaf)
    116     {
    117         typedef std::tuple<ConstructsWithTupleLeaf> d_t;
    118         d_t d((ConstructsWithTupleLeaf()));
    119         d_t d2(static_cast<d_t &&>(d));
    120     }
    121     {
    122         test_sfinae<move_only_ebo>();
    123         test_sfinae<move_only_large>();
    124     }
    125 }
    126