text: //===----------------------------------------------------------------------===//
  //
  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  // See https://llvm.org/LICENSE.txt for license information.
  // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  //
  //===----------------------------------------------------------------------===//
  
  // <tuple>
  
  // template <class... Types> class tuple;
  
  // explicit tuple(const T&...);
  
  // UNSUPPORTED: c++98, c++03
  
  #include <tuple>
  #include <string>
  #include <cassert>
  
  #include "test_macros.h"
  
  template <class ...>
  struct never {
      enum { value = 0 };
  };
  
  struct NoValueCtor
  {
      NoValueCtor() : id(++count) {}
      NoValueCtor(NoValueCtor const & other) : id(other.id) { ++count; }
  
      // The constexpr is required to make is_constructible instantiate this template.
      // The explicit is needed to test-around a similar bug with is_convertible.
      template <class T>
      constexpr explicit NoValueCtor(T)
      { static_assert(never<T>::value, "This should not be instantiated"); }
  
      static int count;
      int id;
  };
  
  int NoValueCtor::count = 0;
  
  
  struct NoValueCtorEmpty
  {
      NoValueCtorEmpty() {}
      NoValueCtorEmpty(NoValueCtorEmpty const &) {}
  
      template <class T>
      constexpr explicit NoValueCtorEmpty(T)
      { static_assert(never<T>::value, "This should not be instantiated"); }
  };
  
  
  struct ImplicitCopy {
    explicit ImplicitCopy(int) {}
    ImplicitCopy(ImplicitCopy const&) {}
  };
  
  // Test that tuple(std::allocator_arg, Alloc, Types const&...) allows implicit
  // copy conversions in return value expressions.
  std::tuple<ImplicitCopy> testImplicitCopy1() {
      ImplicitCopy i(42);
      return {i};
  }
  
  std::tuple<ImplicitCopy> testImplicitCopy2() {
      const ImplicitCopy i(42);
      return {i};
  }
  
  std::tuple<ImplicitCopy> testImplicitCopy3() {
      const ImplicitCopy i(42);
      return i;
  }
  
  int main(int, char**)
  {
      {
          // check that the literal '0' can implicitly initialize a stored pointer.
          std::tuple<int*> t = 0;
          assert(std::get<0>(t) == nullptr);
      }
      {
          std::tuple<int> t(2);
          assert(std::get<0>(t) == 2);
      }
  #if TEST_STD_VER > 11
      {
          constexpr std::tuple<int> t(2);
          static_assert(std::get<0>(t) == 2, "");
      }
      {
          constexpr std::tuple<int> t;
          static_assert(std::get<0>(t) == 0, "");
      }
  #endif
      {
          std::tuple<int, char*> t(2, 0);
          assert(std::get<0>(t) == 2);
          assert(std::get<1>(t) == nullptr);
      }
  #if TEST_STD_VER > 11
      {
          constexpr std::tuple<int, char*> t(2, nullptr);
          static_assert(std::get<0>(t) == 2, "");
          static_assert(std::get<1>(t) == nullptr, "");
      }
  #endif
      {
          std::tuple<int, char*> t(2, nullptr);
          assert(std::get<0>(t) == 2);
          assert(std::get<1>(t) == nullptr);
      }
      {
          std::tuple<int, char*, std::string> t(2, nullptr, "text");
          assert(std::get<0>(t) == 2);
          assert(std::get<1>(t) == nullptr);
          assert(std::get<2>(t) == "text");
      }
      // __tuple_leaf<T> uses is_constructible<T, U> to disable its explicit converting
      // constructor overload __tuple_leaf(U &&). Evaluating is_constructible can cause a compile error.
      // This overload is evaluated when __tuple_leafs copy or move ctor is called.
      // This checks that is_constructible is not evaluated when U == __tuple_leaf.
      {
          std::tuple<int, NoValueCtor, int, int> t(1, NoValueCtor(), 2, 3);
          assert(std::get<0>(t) == 1);
          assert(std::get<1>(t).id == 1);
          assert(std::get<2>(t) == 2);
          assert(std::get<3>(t) == 3);
      }
      {
          std::tuple<int, NoValueCtorEmpty, int, int> t(1, NoValueCtorEmpty(), 2, 3);
          assert(std::get<0>(t) == 1);
          assert(std::get<2>(t) == 2);
          assert(std::get<3>(t) == 3);
      }
  // extensions
  #ifdef _LIBCPP_VERSION
      {
          std::tuple<int, char*, std::string> t(2);
          assert(std::get<0>(t) == 2);
          assert(std::get<1>(t) == nullptr);
          assert(std::get<2>(t) == "");
      }
      {
          std::tuple<int, char*, std::string> t(2, nullptr);
          assert(std::get<0>(t) == 2);
          assert(std::get<1>(t) == nullptr);
          assert(std::get<2>(t) == "");
      }
      {
          std::tuple<int, char*, std::string, double> t(2, nullptr, "text");
          assert(std::get<0>(t) == 2);
          assert(std::get<1>(t) == nullptr);
          assert(std::get<2>(t) == "text");
          assert(std::get<3>(t) == 0.0);
      }
  #endif
  
    return 0;
  }
  