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 // UNSUPPORTED: c++98, c++03
     11 
     12 // <tuple>
     13 
     14 // template <class... Types> class tuple;
     15 
     16 // template <class ...UTypes>
     17 //    EXPLICIT(...) tuple(UTypes&&...)
     18 
     19 // Check that the UTypes... ctor is properly disabled before evaluating any
     20 // SFINAE when the tuple-like copy/move ctor should *clearly* be selected
     21 // instead. This happens 'sizeof...(UTypes) == 1' and the first element of
     22 // 'UTypes...' is an instance of the tuple itself. See PR23256.
     23 
     24 #include <tuple>
     25 #include <memory>
     26 #include <type_traits>
     27 
     28 
     29 struct UnconstrainedCtor {
     30   int value_;
     31 
     32   UnconstrainedCtor() : value_(0) {}
     33 
     34   // Blows up when instantiated for any type other than int. Because the ctor
     35   // is constexpr it is instantiated by 'is_constructible' and 'is_convertible'
     36   // for Clang based compilers. GCC does not instantiate the ctor body
     37   // but it does instantiate the noexcept specifier and it will blow up there.
     38   template <typename T>
     39   constexpr UnconstrainedCtor(T value) noexcept(noexcept(value_ = value))
     40       : value_(static_cast<int>(value))
     41   {
     42       static_assert(std::is_same<int, T>::value, "");
     43   }
     44 };
     45 
     46 struct ExplicitUnconstrainedCtor {
     47   int value_;
     48 
     49   ExplicitUnconstrainedCtor() : value_(0) {}
     50 
     51   template <typename T>
     52   constexpr explicit ExplicitUnconstrainedCtor(T value)
     53     noexcept(noexcept(value_ = value))
     54       : value_(static_cast<int>(value))
     55   {
     56       static_assert(std::is_same<int, T>::value, "");
     57   }
     58 
     59 };
     60 
     61 int main() {
     62     typedef UnconstrainedCtor A;
     63     typedef ExplicitUnconstrainedCtor ExplicitA;
     64     {
     65         static_assert(std::is_copy_constructible<std::tuple<A>>::value, "");
     66         static_assert(std::is_move_constructible<std::tuple<A>>::value, "");
     67         static_assert(std::is_copy_constructible<std::tuple<ExplicitA>>::value, "");
     68         static_assert(std::is_move_constructible<std::tuple<ExplicitA>>::value, "");
     69     }
     70     {
     71         static_assert(std::is_constructible<
     72             std::tuple<A>,
     73             std::allocator_arg_t, std::allocator<void>,
     74             std::tuple<A> const&
     75         >::value, "");
     76         static_assert(std::is_constructible<
     77             std::tuple<A>,
     78             std::allocator_arg_t, std::allocator<void>,
     79             std::tuple<A> &&
     80         >::value, "");
     81         static_assert(std::is_constructible<
     82             std::tuple<ExplicitA>,
     83             std::allocator_arg_t, std::allocator<void>,
     84             std::tuple<ExplicitA> const&
     85         >::value, "");
     86         static_assert(std::is_constructible<
     87             std::tuple<ExplicitA>,
     88             std::allocator_arg_t, std::allocator<void>,
     89             std::tuple<ExplicitA> &&
     90         >::value, "");
     91     }
     92     {
     93         std::tuple<A&&> t(std::forward_as_tuple(A{}));
     94         ((void)t);
     95         std::tuple<ExplicitA&&> t2(std::forward_as_tuple(ExplicitA{}));
     96         ((void)t2);
     97     }
     98 }
     99