blob: bbadf8de16001c16ccb1eea277156b3fb2b03c85 [file] [log] [blame]
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// <tuple>
// template <class... Types> class tuple;
// explicit tuple(const T&...);
// UNSUPPORTED: c++98, c++03
#include <tuple>
#include <string>
#include <cassert>
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"); }
};
int main()
{
{
std::tuple<int> t(2);
assert(std::get<0>(t) == 2);
}
#if _LIBCPP_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 _LIBCPP_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
{
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);
}
}