#include <array>
#include <cassert>
#include <ranges>
#include <string>
#include <tuple>
#include <type_traits>
#include <utility>
namespace my_ns{
struct MyPairLike {
template <std::size_t N>
friend int get(MyPairLike const&)
{
return 0;
}
};
}
namespace std {
template <>
struct tuple_size<my_ns::MyPairLike> : std::integral_constant<std::size_t, 2> {};
template <std::size_t N>
struct tuple_element<N, my_ns::MyPairLike> {
using type = int;
};
}
static_assert(!std::is_constructible_v<std::pair<int,int>, my_ns::MyPairLike const&>);
constexpr bool test() {
{
{
std::array<int, 2> a = {1, 2};
std::pair<int, int> p(a);
assert(p.first == 1);
assert(p.second == 2);
static_assert(!std::is_constructible_v<std::pair<int, int>, std::array<int, 1>>);
static_assert( std::is_constructible_v<std::pair<int, int>, std::array<int, 2>>);
static_assert(!std::is_constructible_v<std::pair<int, int>, std::array<int, 3>>);
}
{
std::tuple<int, int> a = {1, 2};
std::pair<int, int> p(a);
assert(p.first == 1);
assert(p.second == 2);
static_assert(!std::is_constructible_v<std::pair<int, int>, std::tuple<int>>);
static_assert( std::is_constructible_v<std::pair<int, int>, std::tuple<int, int>>);
static_assert(!std::is_constructible_v<std::pair<int, int>, std::tuple<int, int, int>>);
}
{
int data[] = {1, 2, 3, 4, 5};
const std::ranges::subrange a(data);
std::pair<int*, int*> p = a;
assert(p.first == data + 0);
assert(p.second == data + 5);
}
}
{
std::tuple<int, char const*> a = {34, "hello world"};
std::pair<long, std::string> p(a);
assert(p.first == 34);
assert(p.second == std::string("hello world"));
static_assert(!std::is_constructible_v<std::pair<long, std::string>, std::tuple<char*, std::string>>);
static_assert(!std::is_constructible_v<std::pair<long, std::string>, std::tuple<long, void*>>);
static_assert( std::is_constructible_v<std::pair<long, std::string>, std::tuple<long, std::string>>);
}
{
struct NoCopy {
NoCopy() = default;
NoCopy(NoCopy const&) = delete;
NoCopy(NoCopy&&) = default;
};
std::tuple<NoCopy, NoCopy> a;
std::pair<NoCopy, NoCopy> p(std::move(a));
(void)p;
}
{
struct To { };
struct FromImplicit {
constexpr operator To() const { return To{}; }
};
struct FromExplicit {
constexpr explicit operator To() const { return To{}; }
};
{
std::tuple<FromImplicit, float> a = {FromImplicit{}, 2.3f};
std::pair<To, double> p = a;
(void)p;
static_assert(std::is_convertible_v<std::tuple<FromImplicit, float>, std::pair<To, double>>);
}
{
static_assert( std::is_constructible_v<std::pair<To, int>, std::tuple<FromExplicit, int>>);
static_assert(!std::is_convertible_v<std::tuple<FromExplicit, int>, std::pair<To, int>>);
static_assert( std::is_constructible_v<std::pair<int, To>, std::tuple<int, FromExplicit>>);
static_assert(!std::is_convertible_v<std::tuple<int, FromExplicit>, std::pair<int, To>>);
static_assert( std::is_constructible_v<std::pair<To, To>, std::tuple<FromExplicit, FromExplicit>>);
static_assert(!std::is_convertible_v<std::tuple<FromExplicit, FromExplicit>, std::pair<To, To>>);
}
}
return true;
}
int main(int, char**) {
test();
static_assert(test());
return 0;
}