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 // UNSUPPORTED: c++98, c++03
     15 
     16 #include <tuple>
     17 #include <utility>
     18 #include <cassert>
     19 
     20 template <class ConstructFrom>
     21 struct ConstructibleFromT {
     22   ConstructibleFromT() = default;
     23   ConstructibleFromT(ConstructFrom v) : value(v) {}
     24   ConstructFrom value;
     25 };
     26 
     27 template <class AssertOn>
     28 struct CtorAssertsT {
     29   bool defaulted;
     30   CtorAssertsT() : defaulted(true) {}
     31   template <class T>
     32   constexpr CtorAssertsT(T) : defaulted(false) {
     33       static_assert(!std::is_same<T, AssertOn>::value, "");
     34   }
     35 };
     36 
     37 template <class AllowT, class AssertT>
     38 struct AllowAssertT {
     39   AllowAssertT() = default;
     40   AllowAssertT(AllowT) {}
     41   template <class U>
     42   constexpr AllowAssertT(U) {
     43       static_assert(!std::is_same<U, AssertT>::value, "");
     44   }
     45 };
     46 
     47 // Construct a tuple<T1, T2> from pair<int, int> where T1 and T2
     48 // are not constructible from ints but T1 is constructible from std::pair.
     49 // This considers the following constructors:
     50 // (1) tuple(TupleLike) -> checks is_constructible<Tn, int>
     51 // (2) tuple(UTypes...) -> checks is_constructible<T1, pair<int, int>>
     52 //                            and is_default_constructible<T2>
     53 // The point of this test is to ensure that the consideration of (1)
     54 // short circuits before evaluating is_constructible<T2, int>, which
     55 // will cause a static assertion.
     56 void test_tuple_like_lazy_sfinae() {
     57 #if defined(_LIBCPP_VERSION)
     58     // This test requires libc++'s reduced arity initialization.
     59     using T1 = ConstructibleFromT<std::pair<int, int>>;
     60     using T2 = CtorAssertsT<int>;
     61     std::pair<int, int> p(42, 100);
     62     std::tuple<T1, T2> t(p);
     63     assert(std::get<0>(t).value == p);
     64     assert(std::get<1>(t).defaulted);
     65 #endif
     66 }
     67 
     68 
     69 struct NonConstCopyable {
     70   NonConstCopyable() = default;
     71   explicit NonConstCopyable(int v) : value(v) {}
     72   NonConstCopyable(NonConstCopyable&) = default;
     73   NonConstCopyable(NonConstCopyable const&) = delete;
     74   int value;
     75 };
     76 
     77 template <class T>
     78 struct BlowsUpOnConstCopy {
     79   BlowsUpOnConstCopy() = default;
     80   constexpr BlowsUpOnConstCopy(BlowsUpOnConstCopy const&) {
     81       static_assert(!std::is_same<T, T>::value, "");
     82   }
     83   BlowsUpOnConstCopy(BlowsUpOnConstCopy&) = default;
     84 };
     85 
     86 // Test the following constructors:
     87 // (1) tuple(Types const&...)
     88 // (2) tuple(UTypes&&...)
     89 // Test that (1) short circuits before evaluating the copy constructor of the
     90 // second argument. Constructor (2) should be selected.
     91 void test_const_Types_lazy_sfinae()
     92 {
     93     NonConstCopyable v(42);
     94     BlowsUpOnConstCopy<int> b;
     95     std::tuple<NonConstCopyable, BlowsUpOnConstCopy<int>> t(v, b);
     96     assert(std::get<0>(t).value == 42);
     97 }
     98 
     99 int main() {
    100     test_tuple_like_lazy_sfinae();
    101     test_const_Types_lazy_sfinae();
    102 }
    103