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 #include <string>
     23 #include <system_error>
     24 
     25 #include "test_macros.h"
     26 #include "test_convertible.hpp"
     27 #include "MoveOnly.h"
     28 
     29 #if defined(_LIBCPP_ENABLE_TUPLE_IMPLICIT_REDUCED_ARITY_EXTENSION)
     30 #error This macro should not be defined by default
     31 #endif
     32 
     33 struct NoDefault { NoDefault() = delete; };
     34 
     35 
     36 // Make sure the _Up... constructor SFINAEs out when the types that
     37 // are not explicitly initialized are not all default constructible.
     38 // Otherwise, std::is_constructible would return true but instantiating
     39 // the constructor would fail.
     40 void test_default_constructible_extension_sfinae()
     41 {
     42     typedef MoveOnly MO;
     43     typedef NoDefault ND;
     44     {
     45         typedef std::tuple<MO, ND> Tuple;
     46         static_assert(!std::is_constructible<Tuple, MO>::value, "");
     47         static_assert(std::is_constructible<Tuple, MO, ND>::value, "");
     48         static_assert(test_convertible<Tuple, MO, ND>(), "");
     49     }
     50     {
     51         typedef std::tuple<MO, MO, ND> Tuple;
     52         static_assert(!std::is_constructible<Tuple, MO, MO>::value, "");
     53         static_assert(std::is_constructible<Tuple, MO, MO, ND>::value, "");
     54         static_assert(test_convertible<Tuple, MO, MO, ND>(), "");
     55     }
     56     {
     57         // Same idea as above but with a nested tuple type.
     58         typedef std::tuple<MO, ND> Tuple;
     59         typedef std::tuple<MO, Tuple, MO, MO> NestedTuple;
     60 
     61         static_assert(!std::is_constructible<
     62             NestedTuple, MO, MO, MO, MO>::value, "");
     63         static_assert(std::is_constructible<
     64             NestedTuple, MO, Tuple, MO, MO>::value, "");
     65     }
     66 }
     67 
     68 using ExplicitTup = std::tuple<std::string, int, std::error_code>;
     69 ExplicitTup doc_example() {
     70       return ExplicitTup{"hello world", 42}; // explicit constructor called. OK.
     71 }
     72 
     73 // Test that the example given in UsingLibcxx.rst actually works.
     74 void test_example_from_docs() {
     75   auto tup = doc_example();
     76   assert(std::get<0>(tup) == "hello world");
     77   assert(std::get<1>(tup) == 42);
     78   assert(std::get<2>(tup) == std::error_code{});
     79 }
     80 
     81 int main()
     82 {
     83     {
     84         using E = MoveOnly;
     85         using Tup = std::tuple<E, E, E>;
     86         // Test that the reduced arity initialization extension is only
     87         // allowed on the explicit constructor.
     88         static_assert(test_convertible<Tup, E, E, E>(), "");
     89 
     90         Tup t(E(0), E(1));
     91         static_assert(std::is_constructible<Tup, E, E>::value, "");
     92         static_assert(!test_convertible<Tup, E, E>(), "");
     93         assert(std::get<0>(t) == 0);
     94         assert(std::get<1>(t) == 1);
     95         assert(std::get<2>(t) == MoveOnly());
     96 
     97         Tup t2(E(0));
     98         static_assert(std::is_constructible<Tup, E>::value, "");
     99         static_assert(!test_convertible<Tup, E>(), "");
    100         assert(std::get<0>(t) == 0);
    101         assert(std::get<1>(t) == E());
    102         assert(std::get<2>(t) == E());
    103     }
    104     // Check that SFINAE is properly applied with the default reduced arity
    105     // constructor extensions.
    106     test_default_constructible_extension_sfinae();
    107     test_example_from_docs();
    108 }
    109