template<typename _Tp, typename _Up, typename _Vp>
concept __pair_like_convertible_from
- = !range<_Tp> && !is_reference_v<_Vp> && __pair_like<_Tp>
+ = !range<_Tp> && !is_reference_v<_Tp> && __pair_like<_Tp>
&& constructible_from<_Tp, _Up, _Vp>
&& __convertible_to_non_slicing<_Up, tuple_element_t<0, _Tp>>
&& convertible_to<_Vp, tuple_element_t<1, _Tp>>;
// { dg-do compile { target c++20 } }
#include <ranges>
+#include <tuple>
+#include <utility>
using S1 = std::ranges::subrange<int*>;
using S2 = std::ranges::subrange<long*, void*>;
const S2 c2;
static_assert( std::same_as<decltype(std::get<0>(c2)), long*> );
static_assert( std::same_as<decltype(std::get<1>(c2)), void*> );
+
+std::pair<int*, int*> p1 = s1;
+std::pair<long*, void*> p2 = s2;
+std::tuple<int*, int*> t1 = s1;
+std::tuple<long*, void*> t2 = s2;
+
+std::pair<int*, int*> const& p3 = s1;
+std::tuple<int*, int*>&& t3 = s1;
+
+std::pair<int const*, int const*> p4 = s1;
+std::tuple<int const*, void*> t4 = s1;
+
+static_assert( !std::convertible_to<std::ranges::subrange<int const*>, std::pair<int*, int*>> );
+static_assert( !std::convertible_to<std::ranges::subrange<int const*>, std::tuple<int*, int*>> );
+
+static_assert( !std::convertible_to<std::ranges::subrange<int*>, std::pair<long*, long*>> );
+static_assert( !std::convertible_to<std::ranges::subrange<int*>, std::tuple<int, int>> );
+
+struct B {};
+struct D : B {};
+
+std::ranges::subrange<D*> sd;
+std::pair<D*, D*> p5 = sd;
+std::tuple<D const*, D const*> t5 = sd;
+
+static_assert( !std::convertible_to<std::ranges::subrange<D*>, std::pair<B*, B*>> );
+static_assert( !std::convertible_to<std::ranges::subrange<B*>, std::tuple<D*, D*>> );