diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
index adbc6d7b274ef4e9528e10c5a75235bc9f534f20..978578197dc050efaf85a89d5657007cc43b5880 100644
--- a/libstdc++-v3/include/std/ranges
+++ b/libstdc++-v3/include/std/ranges
@@ -724,168 +724,172 @@ namespace __detail
 
 } // namespace __detail
 
-namespace views
+namespace views::__adaptor
 {
-  namespace __adaptor
+  // True if the range adaptor _Adaptor can be applied with _Args.
+  template<typename _Adaptor, typename... _Args>
+    concept __adaptor_invocable
+      = requires { std::declval<_Adaptor>()(declval<_Args>()...); };
+
+  // True if the range adaptor non-closure _Adaptor can be partially applied
+  // with _Args.
+  template<typename _Adaptor, typename... _Args>
+    concept __adaptor_partial_app_viable = (_Adaptor::_S_arity > 1)
+      && (sizeof...(_Args) == _Adaptor::_S_arity - 1)
+      && (constructible_from<decay_t<_Args>, _Args> && ...);
+
+  template<typename _Adaptor, typename... _Args>
+    struct _Partial;
+
+  template<typename _Lhs, typename _Rhs>
+    struct _Pipe;
+
+  // The base class of every range adaptor closure.
+  struct _RangeAdaptorClosure
   {
-    template<typename _Tp>
-      inline constexpr auto
-      __maybe_refwrap(_Tp& __arg)
-      { return reference_wrapper<_Tp>{__arg}; }
+    // range | adaptor is equivalent to adaptor(range).
+    template<typename _Self, typename _Range>
+      requires derived_from<remove_cvref_t<_Self>, _RangeAdaptorClosure>
+	&& __adaptor_invocable<_Self, _Range>
+      friend constexpr auto
+      operator|(_Range&& __r, _Self&& __self)
+      { return std::forward<_Self>(__self)(std::forward<_Range>(__r)); }
+
+    // Compose the adaptors __lhs and __rhs into a pipeline, returning
+    // another range adaptor closure object.
+    template<typename _Lhs, typename _Rhs>
+      requires derived_from<_Lhs, _RangeAdaptorClosure>
+	&& derived_from<_Rhs, _RangeAdaptorClosure>
+      friend constexpr auto
+      operator|(_Lhs __lhs, _Rhs __rhs)
+      { return _Pipe<_Lhs, _Rhs>{std::move(__lhs), std::move(__rhs)}; }
+  };
 
-    template<typename _Tp>
-      inline constexpr auto
-      __maybe_refwrap(const _Tp& __arg)
-      { return reference_wrapper<const _Tp>{__arg}; }
+  // The base class of every range adaptor non-closure.
+  //
+  // The static data member _Derived::_S_arity must contain the total number of
+  // arguments that the adaptor takes, and the class _Derived must introduce
+  // _RangeAdaptor::operator() into the class scope via a using-declaration.
+  template<typename _Derived>
+    struct _RangeAdaptor
+    {
+      // Partially apply the arguments __args to the range adaptor _Derived,
+      // returning a range adaptor closure object.
+      template<typename... _Args>
+	requires __adaptor_partial_app_viable<_Derived, _Args...>
+	constexpr auto
+	operator()(_Args&&... __args) const
+	{
+	  return _Partial<_Derived, decay_t<_Args>...>{std::forward<_Args>(__args)...};
+	}
+    };
 
-    template<typename _Tp>
-      inline constexpr decltype(auto)
-      __maybe_refwrap(_Tp&& __arg)
-      { return std::forward<_Tp>(__arg); }
+  // A range adaptor closure that represents partial application of
+  // the range adaptor _Adaptor with arguments _Args.
+  template<typename _Adaptor, typename... _Args>
+    struct _Partial : _RangeAdaptorClosure
+    {
+      tuple<_Args...> _M_args;
 
-    template<typename _Callable>
-      struct _RangeAdaptorClosure;
+      constexpr
+      _Partial(_Args... __args)
+	: _M_args(std::move(__args)...)
+      { }
 
-    template<typename _Callable>
-      struct _RangeAdaptor
-      {
-      protected:
-	[[no_unique_address]]
-	  __detail::__maybe_present_t<!is_default_constructible_v<_Callable>,
-				      _Callable> _M_callable;
+      // Invoke _Adaptor with arguments __r, _M_args... according to the
+      // value category of the range adaptor closure object.
+      template<typename _Range>
+	requires __adaptor_invocable<_Adaptor, _Range, const _Args&...>
+	constexpr auto
+	operator()(_Range&& __r) const &
+	{
+	  auto __forwarder = [&__r] (const auto&... __args) {
+	    return _Adaptor{}(std::forward<_Range>(__r), __args...);
+	  };
+	  return std::apply(__forwarder, _M_args);
+	}
 
-      public:
-	constexpr
-	_RangeAdaptor(const _Callable& = {})
-	  requires is_default_constructible_v<_Callable>
-	{ }
+      template<typename _Range>
+	requires __adaptor_invocable<_Adaptor, _Range, _Args...>
+	constexpr auto
+	operator()(_Range&& __r) &&
+	{
+	  auto __forwarder = [&__r] (auto&... __args) {
+	    return _Adaptor{}(std::forward<_Range>(__r), std::move(__args)...);
+	  };
+	  return std::apply(__forwarder, _M_args);
+	}
 
-	constexpr
-	_RangeAdaptor(_Callable __callable)
-	  requires (!is_default_constructible_v<_Callable>)
-	  : _M_callable(std::move(__callable))
-	{ }
+      template<typename _Range>
+	constexpr auto
+	operator()(_Range&& __r) const && = delete;
+    };
 
-	template<typename... _Args>
-	  requires (sizeof...(_Args) >= 1)
-	  constexpr auto
-	  operator()(_Args&&... __args) const
-	  {
-	    // [range.adaptor.object]: If a range adaptor object accepts more
-	    // than one argument, then the following expressions are equivalent:
-	    //
-	    //   (1) adaptor(range, args...)
-	    //   (2) adaptor(args...)(range)
-	    //   (3) range | adaptor(args...)
-	    //
-	    // In this case, adaptor(args...) is a range adaptor closure object.
-	    //
-	    // We handle (1) and (2) here, and (3) is just a special case of a
-	    // more general case already handled by _RangeAdaptorClosure.
-	    if constexpr (is_invocable_v<_Callable, _Args...>)
-	      {
-		static_assert(sizeof...(_Args) != 1,
-			      "a _RangeAdaptor that accepts only one argument "
-			      "should be defined as a _RangeAdaptorClosure");
-		// Here we handle adaptor(range, args...) -- just forward all
-		// arguments to the underlying adaptor routine.
-		return _Callable{}(std::forward<_Args>(__args)...);
-	      }
-	    else
-	      {
-		// Here we handle adaptor(args...)(range).
-		// Given args..., we return a _RangeAdaptorClosure that takes a
-		// range argument, such that (2) is equivalent to (1).
-		//
-		// We need to be careful about how we capture args... in this
-		// closure.  By using __maybe_refwrap, we capture lvalue
-		// references by reference (through a reference_wrapper) and
-		// otherwise capture by value.
-		auto __closure
-		  = [...__args(__maybe_refwrap(std::forward<_Args>(__args)))]
-		    <typename _Range> (_Range&& __r) {
-		      // This static_cast has two purposes: it forwards a
-		      // reference_wrapper<T> capture as a T&, and otherwise
-		      // forwards the captured argument as an rvalue.
-		      return _Callable{}(std::forward<_Range>(__r),
-			       (static_cast<unwrap_reference_t
-					    <remove_const_t<decltype(__args)>>>
-				(__args))...);
-		    };
-		using _ClosureType = decltype(__closure);
-		return _RangeAdaptorClosure<_ClosureType>(std::move(__closure));
-	      }
-	  }
-      };
+  // A lightweight specialization of the above primary template for
+  // the common case where _Adaptor accepts a single extra argument.
+  template<typename _Adaptor, typename _Arg>
+    struct _Partial<_Adaptor, _Arg> : _RangeAdaptorClosure
+    {
+      _Arg _M_arg;
 
-    template<typename _Callable>
-      _RangeAdaptor(_Callable) -> _RangeAdaptor<_Callable>;
+      constexpr
+      _Partial(_Arg __arg)
+	: _M_arg(std::move(__arg))
+      { }
 
-    template<typename _Callable>
-      struct _RangeAdaptorClosure : public _RangeAdaptor<_Callable>
-      {
-	using _RangeAdaptor<_Callable>::_RangeAdaptor;
+      template<typename _Range>
+	requires __adaptor_invocable<_Adaptor, _Range, const _Arg&>
+	constexpr auto
+	operator()(_Range&& __r) const &
+	{ return _Adaptor{}(std::forward<_Range>(__r), _M_arg); }
+
+      template<typename _Range>
+	requires __adaptor_invocable<_Adaptor, _Range, _Arg>
+	constexpr auto
+	operator()(_Range&& __r) &&
+	{ return _Adaptor{}(std::forward<_Range>(__r), std::move(_M_arg)); }
+
+      template<typename _Range>
+	constexpr auto
+	operator()(_Range&& __r) const && = delete;
+    };
 
-	template<viewable_range _Range>
-	  requires requires { declval<_Callable>()(declval<_Range>()); }
-	  constexpr auto
-	  operator()(_Range&& __r) const
-	  {
-	    if constexpr (is_default_constructible_v<_Callable>)
-	      return _Callable{}(std::forward<_Range>(__r));
-	    else
-	      return this->_M_callable(std::forward<_Range>(__r));
-	  }
+  template<typename _Lhs, typename _Rhs, typename _Range>
+    concept __pipe_invocable
+      = requires { std::declval<_Rhs>()(std::declval<_Lhs>()(std::declval<_Range>())); };
 
-	template<viewable_range _Range>
-	  requires requires { declval<_Callable>()(declval<_Range>()); }
-	  friend constexpr auto
-	  operator|(_Range&& __r, const _RangeAdaptorClosure& __o)
-	  { return __o(std::forward<_Range>(__r)); }
+  // A range adaptor closure that represents composition of the range
+  // adaptor closures _Lhs and _Rhs.
+  template<typename _Lhs, typename _Rhs>
+    struct _Pipe : _RangeAdaptorClosure
+    {
+      [[no_unique_address]] _Lhs _M_lhs;
+      [[no_unique_address]] _Rhs _M_rhs;
 
-	template<typename _Tp>
-	  friend constexpr auto
-	  operator|(const _RangeAdaptorClosure<_Tp>& __x,
-		    const _RangeAdaptorClosure& __y)
-	  {
-	    if constexpr (is_default_constructible_v<_Tp>
-			  && is_default_constructible_v<_Callable>)
-	      {
-		auto __closure = [] <typename _Up> (_Up&& __e) {
-		  return std::forward<_Up>(__e) | decltype(__x){} | decltype(__y){};
-		};
-		return _RangeAdaptorClosure<decltype(__closure)>(__closure);
-	      }
-	    else if constexpr (is_default_constructible_v<_Tp>
-			       && !is_default_constructible_v<_Callable>)
-	      {
-		auto __closure = [__y] <typename _Up> (_Up&& __e) {
-		  return std::forward<_Up>(__e) | decltype(__x){} | __y;
-		};
-		return _RangeAdaptorClosure<decltype(__closure)>(__closure);
-	      }
-	    else if constexpr (!is_default_constructible_v<_Tp>
-			       && is_default_constructible_v<_Callable>)
-	      {
-		auto __closure = [__x] <typename _Up> (_Up&& __e) {
-		  return std::forward<_Up>(__e) | __x | decltype(__y){};
-		};
-		return _RangeAdaptorClosure<decltype(__closure)>(__closure);
-	      }
-	    else
-	      {
-		auto __closure = [__x, __y] <typename _Up> (_Up&& __e) {
-		  return std::forward<_Up>(__e) | __x | __y;
-		};
-		return _RangeAdaptorClosure<decltype(__closure)>(__closure);
-	      }
-	  }
-      };
+      constexpr
+      _Pipe(_Lhs __lhs, _Rhs __rhs)
+	: _M_lhs(std::move(__lhs)), _M_rhs(std::move(__rhs))
+      { }
 
-    template<typename _Callable>
-      _RangeAdaptorClosure(_Callable) -> _RangeAdaptorClosure<_Callable>;
-  } // namespace __adaptor
-} // namespace views
+      // Invoke _M_rhs(_M_lhs(__r)) according to the value category of this
+      // range adaptor closure object.
+      template<typename _Range>
+	requires __pipe_invocable<const _Lhs&, const _Rhs&, _Range>
+	constexpr auto
+	operator()(_Range&& __r) const &
+	{ return _M_rhs(_M_lhs(std::forward<_Range>(__r))); }
+
+      template<typename _Range>
+	requires __pipe_invocable<_Lhs, _Rhs, _Range>
+	constexpr auto
+	operator()(_Range&& __r) &&
+	{ return std::move(_M_rhs)(std::move(_M_lhs)(std::forward<_Range>(__r))); }
+
+      template<typename _Range>
+	constexpr auto
+	operator()(_Range&& __r) const && = delete;
+    };
+} // namespace views::__adaptor
 
   template<range _Range> requires is_object_v<_Range>
     class ref_view : public view_interface<ref_view<_Range>>
@@ -941,20 +945,37 @@ namespace views
 
   namespace views
   {
-    inline constexpr __adaptor::_RangeAdaptorClosure all
-      = [] <viewable_range _Range> (_Range&& __r)
-      {
-	if constexpr (view<decay_t<_Range>>)
-	  return std::forward<_Range>(__r);
-	else if constexpr (requires { ref_view{std::forward<_Range>(__r)}; })
-	  return ref_view{std::forward<_Range>(__r)};
-	else
-	  return subrange{std::forward<_Range>(__r)};
-      };
+    namespace __detail
+    {
+      template<typename _Range>
+	concept __can_ref_view = requires { ref_view{std::declval<_Range>()}; };
+
+      template<typename _Range>
+	concept __can_subrange = requires { subrange{std::declval<_Range>()}; };
+    } // namespace __detail
+
+    struct _All : __adaptor::_RangeAdaptorClosure
+    {
+      template<viewable_range _Range>
+	requires view<decay_t<_Range>>
+	  || __detail::__can_ref_view<_Range>
+	  || __detail::__can_subrange<_Range>
+	constexpr auto
+	operator()(_Range&& __r) const
+	{
+	  if constexpr (view<decay_t<_Range>>)
+	    return std::forward<_Range>(__r);
+	  else if constexpr (__detail::__can_ref_view<_Range>)
+	    return ref_view{std::forward<_Range>(__r)};
+	  else
+	    return subrange{std::forward<_Range>(__r)};
+	}
+    };
+
+    inline constexpr _All all;
 
     template<viewable_range _Range>
       using all_t = decltype(all(std::declval<_Range>()));
-
   } // namespace views
 
   // XXX: the following algos are copied from ranges_algo.h to avoid a circular
@@ -1305,11 +1326,28 @@ namespace views
 
   namespace views
   {
-    inline constexpr __adaptor::_RangeAdaptor filter
-      = [] <viewable_range _Range, typename _Pred> (_Range&& __r, _Pred&& __p)
-      {
-	return filter_view{std::forward<_Range>(__r), std::forward<_Pred>(__p)};
-      };
+    namespace __detail
+    {
+      template<typename _Range, typename _Pred>
+	concept __can_filter_view
+	  = requires { filter_view{std::declval<_Range>(), std::declval<_Pred>()}; };
+    } // namespace __detail
+
+    struct _Filter : __adaptor::_RangeAdaptor<_Filter>
+    {
+      template<viewable_range _Range, typename _Pred>
+	requires __detail::__can_filter_view<_Range, _Pred>
+	constexpr auto
+	operator()(_Range&& __r, _Pred&& __p) const
+	{
+	  return filter_view{std::forward<_Range>(__r), std::forward<_Pred>(__p)};
+	}
+
+      using _RangeAdaptor<_Filter>::operator();
+      static constexpr int _S_arity = 2;
+    };
+
+    inline constexpr _Filter filter;
   } // namespace views
 
   template<input_range _Vp, copy_constructible _Fp>
@@ -1653,11 +1691,28 @@ namespace views
 
   namespace views
   {
-    inline constexpr __adaptor::_RangeAdaptor transform
-      = [] <viewable_range _Range, typename _Fp> (_Range&& __r, _Fp&& __f)
-      {
-	return transform_view{std::forward<_Range>(__r), std::forward<_Fp>(__f)};
-      };
+    namespace __detail
+    {
+      template<typename _Range, typename _Fp>
+	concept __can_transform_view
+	  = requires { transform_view{std::declval<_Range>(), std::declval<_Fp>()}; };
+    } // namespace __detail
+
+    struct _Transform : __adaptor::_RangeAdaptor<_Transform>
+    {
+      template<viewable_range _Range, typename _Fp>
+	requires __detail::__can_transform_view<_Range, _Fp>
+	constexpr auto
+	operator()(_Range&& __r, _Fp&& __f) const
+	{
+	  return transform_view{std::forward<_Range>(__r), std::forward<_Fp>(__f)};
+	}
+
+      using _RangeAdaptor<_Transform>::operator();
+      static constexpr int _S_arity = 2;
+    };
+
+    inline constexpr _Transform transform;
   } // namespace views
 
   template<view _Vp>
@@ -1816,11 +1871,28 @@ namespace views
 
   namespace views
   {
-    inline constexpr __adaptor::_RangeAdaptor take
-      = [] <viewable_range _Range, typename _Tp> (_Range&& __r, _Tp&& __n)
-      {
-	return take_view{std::forward<_Range>(__r), std::forward<_Tp>(__n)};
-      };
+    namespace __detail
+    {
+      template<typename _Range, typename _Tp>
+	concept __can_take_view
+	  = requires { take_view{std::declval<_Range>(), std::declval<_Tp>()}; };
+    } // namespace __detail
+
+    struct _Take : __adaptor::_RangeAdaptor<_Take>
+    {
+      template<viewable_range _Range, typename _Tp>
+	requires __detail::__can_take_view<_Range, _Tp>
+	constexpr auto
+	operator()(_Range&& __r, _Tp&& __n) const
+	{
+	  return take_view{std::forward<_Range>(__r), std::forward<_Tp>(__n)};
+	}
+
+      using _RangeAdaptor<_Take>::operator();
+      static constexpr int _S_arity = 2;
+    };
+
+    inline constexpr _Take take;
   } // namespace views
 
   template<view _Vp, typename _Pred>
@@ -1918,11 +1990,28 @@ namespace views
 
   namespace views
   {
-    inline constexpr __adaptor::_RangeAdaptor take_while
-      = [] <viewable_range _Range, typename _Pred> (_Range&& __r, _Pred&& __p)
-      {
-	return take_while_view{std::forward<_Range>(__r), std::forward<_Pred>(__p)};
-      };
+    namespace __detail
+    {
+      template<typename _Range, typename _Pred>
+	concept __can_take_while_view
+	  = requires { take_while_view{std::declval<_Range>(), std::declval<_Pred>()}; };
+    } // namespace __detail
+
+    struct _TakeWhile : __adaptor::_RangeAdaptor<_TakeWhile>
+    {
+      template<viewable_range _Range, typename _Pred>
+	requires __detail::__can_take_while_view<_Range, _Pred>
+	constexpr auto
+	operator()(_Range&& __r, _Pred&& __p) const
+	{
+	  return take_while_view{std::forward<_Range>(__r), std::forward<_Pred>(__p)};
+	}
+
+      using _RangeAdaptor<_TakeWhile>::operator();
+      static constexpr int _S_arity = 2;
+    };
+
+    inline constexpr _TakeWhile take_while;
   } // namespace views
 
   template<view _Vp>
@@ -2020,11 +2109,28 @@ namespace views
 
   namespace views
   {
-    inline constexpr __adaptor::_RangeAdaptor drop
-      = [] <viewable_range _Range, typename _Tp> (_Range&& __r, _Tp&& __n)
-      {
-	return drop_view{std::forward<_Range>(__r), std::forward<_Tp>(__n)};
-      };
+    namespace __detail
+    {
+      template<typename _Range, typename _Tp>
+	concept __can_drop_view
+	  = requires { drop_view{std::declval<_Range>(), std::declval<_Tp>()}; };
+    } // namespace __detail
+
+    struct _Drop : __adaptor::_RangeAdaptor<_Drop>
+    {
+      template<viewable_range _Range, typename _Tp>
+	requires __detail::__can_drop_view<_Range, _Tp>
+	constexpr auto
+	operator()(_Range&& __r, _Tp&& __n) const
+	{
+	  return drop_view{std::forward<_Range>(__r), std::forward<_Tp>(__n)};
+	}
+
+      using _RangeAdaptor<_Drop>::operator();
+      static constexpr int _S_arity = 2;
+    };
+
+    inline constexpr _Drop drop;
   } // namespace views
 
   template<view _Vp, typename _Pred>
@@ -2085,12 +2191,29 @@ namespace views
 
   namespace views
   {
-    inline constexpr __adaptor::_RangeAdaptor drop_while
-      = [] <viewable_range _Range, typename _Pred> (_Range&& __r, _Pred&& __p)
-      {
-	return drop_while_view{std::forward<_Range>(__r),
-			       std::forward<_Pred>(__p)};
-      };
+    namespace __detail
+    {
+      template<typename _Range, typename _Pred>
+	concept __can_drop_while_view
+	  = requires { drop_while_view{std::declval<_Range>(), std::declval<_Pred>()}; };
+    } // namespace __detail
+
+    struct _DropWhile : __adaptor::_RangeAdaptor<_DropWhile>
+    {
+      template<viewable_range _Range, typename _Pred>
+	requires __detail::__can_drop_while_view<_Range, _Pred>
+	constexpr auto
+	operator()(_Range&& __r, _Pred&& __p) const
+	{
+	  return drop_while_view{std::forward<_Range>(__r),
+				 std::forward<_Pred>(__p)};
+	}
+
+      using _RangeAdaptor<_DropWhile>::operator();
+      static constexpr int _S_arity = 2;
+    };
+
+    inline constexpr _DropWhile drop_while;
   } // namespace views
 
   template<input_range _Vp>
@@ -2409,13 +2532,27 @@ namespace views
 
   namespace views
   {
-    inline constexpr __adaptor::_RangeAdaptorClosure join
-      = [] <viewable_range _Range> (_Range&& __r)
-      {
-	// _GLIBCXX_RESOLVE_LIB_DEFECTS
-	// 3474. Nesting join_views is broken because of CTAD
-	return join_view<views::all_t<_Range>>{std::forward<_Range>(__r)};
-      };
+    namespace __detail
+    {
+      template<typename _Range>
+	concept __can_join_view
+	  = requires { join_view<all_t<_Range>>{std::declval<_Range>()}; };
+    } // namespace __detail
+
+    struct _Join : __adaptor::_RangeAdaptorClosure
+    {
+      template<viewable_range _Range>
+	requires __detail::__can_join_view<_Range>
+	constexpr auto
+	operator()(_Range&& __r) const
+	{
+	  // _GLIBCXX_RESOLVE_LIB_DEFECTS
+	  // 3474. Nesting join_views is broken because of CTAD
+	  return join_view<all_t<_Range>>{std::forward<_Range>(__r)};
+	}
+    };
+
+    inline constexpr _Join join;
   } // namespace views
 
   namespace __detail
@@ -2784,9 +2921,9 @@ namespace views
       }
     };
 
-  template<typename _Range, typename _Pred>
-    split_view(_Range&&, _Pred&&)
-      -> split_view<views::all_t<_Range>, views::all_t<_Pred>>;
+  template<typename _Range, typename _Pattern>
+    split_view(_Range&&, _Pattern&&)
+      -> split_view<views::all_t<_Range>, views::all_t<_Pattern>>;
 
   template<input_range _Range>
     split_view(_Range&&, range_value_t<_Range>)
@@ -2794,11 +2931,28 @@ namespace views
 
   namespace views
   {
-    inline constexpr __adaptor::_RangeAdaptor split
-      = [] <viewable_range _Range, typename _Fp> (_Range&& __r, _Fp&& __f)
-      {
-	return split_view{std::forward<_Range>(__r), std::forward<_Fp>(__f)};
-      };
+    namespace __detail
+    {
+      template<typename _Range, typename _Pattern>
+	concept __can_split_view
+	  = requires { split_view{std::declval<_Range>(), std::declval<_Pattern>()}; };
+    } // namespace __detail
+
+    struct _Split : __adaptor::_RangeAdaptor<_Split>
+    {
+      template<viewable_range _Range, typename _Pattern>
+	requires __detail::__can_split_view<_Range, _Pattern>
+	constexpr auto
+	operator()(_Range&& __r, _Pattern&& __f) const
+	{
+	  return split_view{std::forward<_Range>(__r), std::forward<_Pattern>(__f)};
+	}
+
+      using _RangeAdaptor<_Split>::operator();
+      static constexpr int _S_arity = 2;
+    };
+
+    inline constexpr _Split split;
   } // namespace views
 
   namespace views
@@ -2911,16 +3065,33 @@ namespace views
 
   namespace views
   {
-    inline constexpr __adaptor::_RangeAdaptorClosure common
-      = [] <viewable_range _Range> (_Range&& __r)
-      {
-	if constexpr (common_range<_Range>
-		      && requires { views::all(std::forward<_Range>(__r)); })
-	  return views::all(std::forward<_Range>(__r));
-	else
-	  return common_view{std::forward<_Range>(__r)};
-      };
+    namespace __detail
+    {
+      template<typename _Range>
+	concept __already_common = common_range<_Range>
+	  && requires { views::all(std::declval<_Range>()); };
+
+      template<typename _Range>
+	concept __can_common_view
+	  = requires { common_view{std::declval<_Range>()}; };
+    } // namespace __detail
+
+    struct _Common : __adaptor::_RangeAdaptorClosure
+    {
+      template<viewable_range _Range>
+	requires __detail::__already_common<_Range>
+	  || __detail::__can_common_view<_Range>
+	constexpr auto
+	operator()(_Range&& __r) const
+	{
+	  if constexpr (__detail::__already_common<_Range>)
+	    return views::all(std::forward<_Range>(__r));
+	  else
+	    return common_view{std::forward<_Range>(__r)};
+	}
+    };
 
+    inline constexpr _Common common;
   } // namespace views
 
   template<view _Vp>
@@ -3016,27 +3187,40 @@ namespace views
 
       template<typename _Vp>
 	inline constexpr bool __is_reverse_view<reverse_view<_Vp>> = true;
-    }
 
-    inline constexpr __adaptor::_RangeAdaptorClosure reverse
-      = [] <viewable_range _Range> (_Range&& __r)
-      {
-	using _Tp = remove_cvref_t<_Range>;
-	if constexpr (__detail::__is_reverse_view<_Tp>)
-	  return std::forward<_Range>(__r).base();
-	else if constexpr (__detail::__is_reversible_subrange<_Tp>)
-	  {
-	    using _Iter = decltype(ranges::begin(__r).base());
-	    if constexpr (sized_range<_Tp>)
-	      return subrange<_Iter, _Iter, subrange_kind::sized>
-		      (__r.end().base(), __r.begin().base(), __r.size());
-	    else
-	      return subrange<_Iter, _Iter, subrange_kind::unsized>
-		      (__r.end().base(), __r.begin().base());
-	  }
-	else
-	  return reverse_view{std::forward<_Range>(__r)};
-      };
+      template<typename _Range>
+	concept __can_reverse_view
+	  = requires { reverse_view{std::declval<_Range>()}; };
+    } // namespace __detail
+
+    struct _Reverse : __adaptor::_RangeAdaptorClosure
+    {
+      template<viewable_range _Range>
+	requires __detail::__is_reverse_view<remove_cvref_t<_Range>>
+	  || __detail::__is_reversible_subrange<remove_cvref_t<_Range>>
+	  || __detail::__can_reverse_view<_Range>
+	constexpr auto
+	operator()(_Range&& __r) const
+	{
+	  using _Tp = remove_cvref_t<_Range>;
+	  if constexpr (__detail::__is_reverse_view<_Tp>)
+	    return std::forward<_Range>(__r).base();
+	  else if constexpr (__detail::__is_reversible_subrange<_Tp>)
+	    {
+	      using _Iter = decltype(ranges::begin(__r).base());
+	      if constexpr (sized_range<_Tp>)
+		return subrange<_Iter, _Iter, subrange_kind::sized>
+			{__r.end().base(), __r.begin().base(), __r.size()};
+	      else
+		return subrange<_Iter, _Iter, subrange_kind::unsized>
+			{__r.end().base(), __r.begin().base()};
+	    }
+	  else
+	    return reverse_view{std::forward<_Range>(__r)};
+	}
+    };
+
+    inline constexpr _Reverse reverse;
   } // namespace views
 
   namespace __detail
@@ -3335,16 +3519,29 @@ namespace views
 
   namespace views
   {
+    namespace __detail
+    {
+      template<size_t _Nm, typename _Range>
+	concept __can_elements_view
+	  = requires { elements_view<all_t<_Range>, _Nm>{std::declval<_Range>()}; };
+    } // namespace __detail
+
     template<size_t _Nm>
-    inline constexpr __adaptor::_RangeAdaptorClosure elements
-      = [] <viewable_range _Range> (_Range&& __r)
+      struct _Elements : __adaptor::_RangeAdaptorClosure
       {
-	using _El = elements_view<views::all_t<_Range>, _Nm>;
-	return _El{std::forward<_Range>(__r)};
+	template<viewable_range _Range>
+	  requires __detail::__can_elements_view<_Nm, _Range>
+	  constexpr auto
+	  operator()(_Range&& __r) const
+	  {
+	    return elements_view<all_t<_Range>, _Nm>{std::forward<_Range>(__r)};
+	  }
       };
 
-    inline constexpr __adaptor::_RangeAdaptorClosure keys = elements<0>;
-    inline constexpr __adaptor::_RangeAdaptorClosure values = elements<1>;
+    template<size_t _Nm>
+      inline constexpr _Elements<_Nm> elements;
+    inline constexpr auto keys = elements<0>;
+    inline constexpr auto values = elements<1>;
   } // namespace views
 
 } // namespace ranges
diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/99433.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/99433.cc
new file mode 100644
index 0000000000000000000000000000000000000000..b9d17942e176d0821d4774733eae804aa6ddfc2c
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/ranges/adaptors/99433.cc
@@ -0,0 +1,41 @@
+// Copyright (C) 2021 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+// PR libstdc++/99433
+
+#include <ranges>
+#include <vector>
+
+template <typename underlying_adaptor_t>
+struct deep
+{
+  underlying_adaptor_t adaptor;
+
+  template <typename range_t>
+  friend auto operator|(range_t &range, deep const &me)
+  {
+   return me.adaptor(range[0]);
+  }
+};
+
+auto f = [] (auto nucl) { return nucl + ' '; };
+auto complement = deep{std::views::transform(f)};
+std::vector<std::vector<char>> foo{};
+auto v = foo | complement;
diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/all.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/all.cc
index 33e4b96686e3df4b7896cfa4ed8796c45e150dc1..42913ad38a303ce89cb97beca01d2ff3c673ae5f 100644
--- a/libstdc++-v3/testsuite/std/ranges/adaptors/all.cc
+++ b/libstdc++-v3/testsuite/std/ranges/adaptors/all.cc
@@ -103,6 +103,12 @@ static_assert(std::is_empty_v<decltype(views::common
 				       | views::common
 				       | views::keys
 				       | views::reverse)>);
+#if 0
+// Adding empty range adaptor closure objects to a pipeline used to not
+// increase the size of the pipeline, but now that our range adaptor closure
+// objects derive from a common empty base class, [[no_unique_address]] can no
+// longer make two empty adjacent range adaptor closure objects occupy the same
+// data member address.
 static_assert(sizeof(decltype(views::take(5) | views::drop(5)))
 	      == sizeof(decltype(views::take(5)
 				 | views::join
@@ -111,6 +117,18 @@ static_assert(sizeof(decltype(views::take(5) | views::drop(5)))
 				 | views::keys
 				 | views::drop(5)
 				 | views::reverse)));
+#endif
+
+template<auto all = views::all>
+void
+test05()
+{
+  // Verify SFINAE behavior.
+  static_assert(!requires { all(); });
+  static_assert(!requires { all(0, 0); });
+  static_assert(!requires { all(0); });
+  static_assert(!requires { 0 | all; });
+}
 
 int
 main()
@@ -119,4 +137,5 @@ main()
   test02();
   static_assert(test03());
   static_assert(test04());
+  test05();
 }
diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/common.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/common.cc
index 719b25be006a5e00e7e0da4b6551a08e00387957..085e8ff907dd80d3965e230cf15de97ab704d83f 100644
--- a/libstdc++-v3/testsuite/std/ranges/adaptors/common.cc
+++ b/libstdc++-v3/testsuite/std/ranges/adaptors/common.cc
@@ -60,9 +60,21 @@ test02()
   VERIFY( std::count(v2.begin(), v2.end(), 1) == 2);
 }
 
+template<auto common = views::common>
+void
+test03()
+{
+  // Verify SFINAE behavior.
+  static_assert(!requires { common(); });
+  static_assert(!requires { common(0, 0); });
+  static_assert(!requires { common(0); });
+  static_assert(!requires { 0 | common; });
+}
+
 int
 main()
 {
   test01();
   test02();
+  test03();
 }
diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/drop.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/drop.cc
index 19afba8a9ae075c8d2e25cb2e36cbbcb3743a9cb..c0525109bd1be31e2c55594f0c850f49ba40216e 100644
--- a/libstdc++-v3/testsuite/std/ranges/adaptors/drop.cc
+++ b/libstdc++-v3/testsuite/std/ranges/adaptors/drop.cc
@@ -258,6 +258,23 @@ test08()
   VERIFY( ra_test_wrapper<long>::increment_count == 0 );
 }
 
+template<auto drop = views::drop>
+void
+test09()
+{
+  // Verify SFINAE behavior.
+  extern int x[5];
+  int* n = 0;
+  static_assert(!requires { drop(); });
+  static_assert(!requires { drop(x, n, n); });
+  static_assert(!requires { drop(x, n); });
+  static_assert(!requires { drop(n)(x); });
+  static_assert(!requires { x | (drop(n) | views::all); });
+  static_assert(!requires { (drop(n) | views::all)(x); });
+  static_assert(!requires { drop | views::all; });
+  static_assert(!requires { views::all | drop; });
+}
+
 int
 main()
 {
@@ -269,4 +286,5 @@ main()
   test06();
   test07();
   test08();
+  test09();
 }
diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/drop_while.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/drop_while.cc
index e807388538ba9bbd14fa3f1dce68510191969fbf..58489d54f8965e9fef2052beada7d8369f8b46f4 100644
--- a/libstdc++-v3/testsuite/std/ranges/adaptors/drop_while.cc
+++ b/libstdc++-v3/testsuite/std/ranges/adaptors/drop_while.cc
@@ -89,6 +89,23 @@ test03()
   VERIFY( ranges::equal(v, (int[]){3,4,5}) );
 }
 
+template<auto drop_while = views::drop_while>
+void
+test04()
+{
+  // Verify SFINAE behavior.
+  extern int x[5];
+  auto p = [] (int*) { return true; };
+  static_assert(!requires { drop_while(); });
+  static_assert(!requires { drop_while(x, p, p); });
+  static_assert(!requires { drop_while(x, p); });
+  static_assert(!requires { drop_while(p)(x); });
+  static_assert(!requires { x | (drop_while(p) | views::all); });
+  static_assert(!requires { (drop_while(p) | views::all)(x); });
+  static_assert(!requires { drop_while | views::all; });
+  static_assert(!requires { views::all | drop_while; });
+}
+
 int
 main()
 {
@@ -96,4 +113,5 @@ main()
   test02();
   test03<forward_iterator_wrapper>();
   test03<random_access_iterator_wrapper>();
+  test04();
 }
diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/elements.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/elements.cc
index 768077720068acf457736eeee170ed449585c764..b0d122f8db5f2dc59bd658baa813bf8c1f149c10 100644
--- a/libstdc++-v3/testsuite/std/ranges/adaptors/elements.cc
+++ b/libstdc++-v3/testsuite/std/ranges/adaptors/elements.cc
@@ -89,10 +89,22 @@ test03()
   VERIFY( (next(b_const, 2) - b_const) == 2 );
 }
 
+template<auto elements = views::elements<0>>
+void
+test04()
+{
+  // Verify SFINAE behavior.
+  static_assert(!requires { elements(); });
+  static_assert(!requires { elements(0, 0); });
+  static_assert(!requires { elements(0); });
+  static_assert(!requires { 0 | elements; });
+}
+
 int
 main()
 {
   test01();
   test02();
   test03();
+  test04();
 }
diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/filter.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/filter.cc
index c60eec51368c4ee9e266683e1f0c0308d7b21dd9..e0f6b8d4c4b439e8f8d2c46ac7d536fc77d82bbe 100644
--- a/libstdc++-v3/testsuite/std/ranges/adaptors/filter.cc
+++ b/libstdc++-v3/testsuite/std/ranges/adaptors/filter.cc
@@ -123,6 +123,23 @@ test05()
   VERIFY( ranges::equal(v, (int[]){2,4}) );
 }
 
+template<auto filter = views::filter>
+void
+test06()
+{
+  // Verify SFINAE behavior.
+  extern int x[5];
+  auto p = [] (int*) { return true; };
+  static_assert(!requires { filter(); });
+  static_assert(!requires { filter(x, p, p); });
+  static_assert(!requires { filter(x, p); });
+  static_assert(!requires { filter(p)(x); });
+  static_assert(!requires { x | (filter(p) | views::all); });
+  static_assert(!requires { (filter(p) | views::all)(x); });
+  static_assert(!requires { filter | views::all; });
+  static_assert(!requires { views::all | filter; });
+}
+
 int
 main()
 {
@@ -132,4 +149,5 @@ main()
   test04();
   test05<forward_iterator_wrapper>();
   test05<random_access_iterator_wrapper>();
+  test06();
 }
diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/join.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/join.cc
index 6d780f4887b43a7e90bdccfe7c0b287d912cef8e..fb06a7698afc1d75fc598858d126934d9ff01556 100644
--- a/libstdc++-v3/testsuite/std/ranges/adaptors/join.cc
+++ b/libstdc++-v3/testsuite/std/ranges/adaptors/join.cc
@@ -149,6 +149,17 @@ test08()
   VERIFY( i->a == 5 );
 }
 
+template<auto join = views::join>
+void
+test09()
+{
+  // Verify SFINAE behavior.
+  static_assert(!requires { join(); });
+  static_assert(!requires { join(0, 0); });
+  static_assert(!requires { join(0); });
+  static_assert(!requires { 0 | join; });
+}
+
 int
 main()
 {
@@ -160,4 +171,5 @@ main()
   test06();
   test07();
   test08();
+  test09();
 }
diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/p2281.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/p2281.cc
new file mode 100644
index 0000000000000000000000000000000000000000..c916a5ea8b7a9eb0f08aadb83339e45f6a45b853
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/ranges/adaptors/p2281.cc
@@ -0,0 +1,83 @@
+// Copyright (C) 2021 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <ranges>
+#include <string>
+#include <string_view>
+#include <testsuite_hooks.h>
+
+namespace ranges = std::ranges;
+namespace views = std::ranges::views;
+
+// Verify P2281 changes to the forwarding semantics of partial application
+// and composition of range adaptor objects.
+
+void
+test01()
+{
+  auto split_into_strings = [] (auto p) {
+    return views::split(p) | views::transform([](auto r){
+      return std::string(r.begin(), ranges::next(r.begin(), r.end()));
+    });
+  };
+  constexpr std::string_view s = "hello world";
+  constexpr std::string_view p = " ";
+  constexpr auto v1 = s | split_into_strings(p);
+  constexpr auto v2 = split_into_strings(p)(s);
+  VERIFY( ranges::equal(v1, (std::string_view[]){"hello", "world"}) );
+  VERIFY( ranges::equal(v2, (std::string_view[]){"hello", "world"}) );
+}
+
+struct move_only_range
+{
+  move_only_range() { }
+  move_only_range(move_only_range&&);
+  move_only_range& operator=(move_only_range&&);
+  move_only_range(const move_only_range&) = delete;
+  move_only_range& operator=(const move_only_range&) = delete;
+  char* begin();
+  char* end();
+};
+
+template<>
+  inline constexpr bool std::ranges::enable_view<move_only_range> = true;
+
+template<auto split = views::split>
+void
+test02()
+{
+  std::string_view s;
+  move_only_range p;
+  static_assert(requires { s | split(std::move(p)); });
+  static_assert(requires { split(std::move(p))(s); });
+  static_assert(requires { split(std::move(p)) | views::all; });
+  static_assert(requires { views::all | split(std::move(p)); });
+  static_assert(!requires { split(p); });
+  static_assert(!requires { split(p) | views::all; });
+  static_assert(!requires { views::all | split(p); });
+}
+
+int
+main()
+{
+  test01();
+  test02();
+}
diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/reverse.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/reverse.cc
index 0d52498e207f250e33cc9f80c5c9344adaf32881..47e34eb6581fe2ea763370aabe5eb6e49473c288 100644
--- a/libstdc++-v3/testsuite/std/ranges/adaptors/reverse.cc
+++ b/libstdc++-v3/testsuite/std/ranges/adaptors/reverse.cc
@@ -138,7 +138,8 @@ namespace test_ns
   void make_reverse_iterator(T&&) {}
 } // namespace test_ns
 
-void test06()
+void
+test06()
 {
   // Check that views::reverse works and does not use ADL which could lead
   // to accidentally finding test_ns::make_reverse_iterator(A*).
@@ -149,6 +150,17 @@ void test06()
   static_assert( std::ranges::range<const V> );
 }
 
+template<auto reverse = views::reverse>
+void
+test07()
+{
+  // Verify SFINAE behavior.
+  static_assert(!requires { reverse(); });
+  static_assert(!requires { reverse(0, 0); });
+  static_assert(!requires { reverse(0); });
+  static_assert(!requires { 0 | reverse; });
+}
+
 int
 main()
 {
@@ -158,4 +170,5 @@ main()
   test04();
   test05();
   test06();
+  test07();
 }
diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/split.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/split.cc
index dc7f55a2f92c8468de207a12010619cc312cb8fd..b9fb3728708adb2ff89f41775819d91bdfa7070c 100644
--- a/libstdc++-v3/testsuite/std/ranges/adaptors/split.cc
+++ b/libstdc++-v3/testsuite/std/ranges/adaptors/split.cc
@@ -39,7 +39,7 @@ test01()
 {
   auto x = "the  quick  brown  fox"sv;
   auto p = std::string{"  "};
-  auto v = x | views::split(p);
+  auto v = x | views::split(views::all(p)); // views::all is needed here after P2281.
   auto i = v.begin();
   VERIFY( ranges::equal(*i++, "the"sv) );
   VERIFY( ranges::equal(*i++, "quick"sv) );
@@ -83,7 +83,7 @@ test04()
   static_assert(!ranges::view<decltype(p)>);
   static_assert(std::same_as<decltype(p | views::all),
 			     ranges::ref_view<decltype(p)>>);
-  auto v = x | views::split(p);
+  auto v = x | views::split(views::all(p)); // views::all is needed here after P2281.
   auto i = v.begin();
   VERIFY( ranges::equal(*i++, "the"sv) );
   VERIFY( ranges::equal(*i++, "quick"sv) );
@@ -152,6 +152,36 @@ test08()
   VERIFY( i == v.end() );
 }
 
+template<auto split = views::split>
+void
+test09()
+{
+  // Verify SFINAE behavior.
+  std::string s, p;
+  static_assert(!requires { split(); });
+  static_assert(!requires { split(s, p, 0); });
+  static_assert(!requires { split(p)(); });
+  static_assert(!requires { s | split; });
+
+  static_assert(!requires { s | split(p); });
+  static_assert(!requires { split(p)(s); });
+  static_assert(!requires { s | (split(p) | views::all); });
+  static_assert(!requires { (split(p) | views::all)(s); });
+
+  static_assert(requires { s | split(views::all(p)); });
+  static_assert(requires { split(views::all(p))(s); });
+  static_assert(requires { s | (split(views::all(p)) | views::all); });
+  static_assert(requires { (split(views::all(p)) | views::all)(s); });
+
+  auto adapt = split(p);
+  static_assert(requires { s | adapt; });
+  static_assert(requires { adapt(s); });
+
+  auto adapt2 = split(p) | views::all;
+  static_assert(requires { s | adapt2; });
+  static_assert(requires { adapt2(s); });
+}
+
 int
 main()
 {
@@ -163,4 +193,5 @@ main()
   test06();
   test07();
   test08();
+  test09();
 }
diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/split_neg.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/split_neg.cc
index fb84049711f458c6f2587b6a89a855df1a1858d6..4229314a9dc5e47e5499093d4fb13a99f0590993 100644
--- a/libstdc++-v3/testsuite/std/ranges/adaptors/split_neg.cc
+++ b/libstdc++-v3/testsuite/std/ranges/adaptors/split_neg.cc
@@ -30,8 +30,7 @@ test01()
 {
   using namespace std::literals;
   auto x = "the  quick  brown  fox"sv;
-  auto v = views::split(x, std::initializer_list<char>{' ', ' '});
-  v.begin(); // { dg-error "" }
+  auto v = views::split(x, std::initializer_list<char>{' ', ' '}); // { dg-error "no match" }
 }
 
 void
@@ -39,11 +38,8 @@ test02()
 {
   using namespace std::literals;
   auto x = "the  quick  brown  fox"sv;
-  auto v = x | views::split(std::initializer_list<char>{' ', ' '}); // { dg-error "no match" }
-  v.begin();
+  auto v1 = views::split(std::initializer_list<char>{' ', ' '})(x); // { dg-error "deleted" }
+  auto v2 = x | views::split(std::initializer_list<char>{' ', ' '}); // { dg-error "no match" }
 }
 
 // { dg-prune-output "in requirements" }
-// { dg-error "deduction failed" "" { target *-*-* } 0 }
-// { dg-error "no match" "" { target *-*-* } 0 }
-// { dg-error "constraint failure" "" { target *-*-* } 0 }
diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/take.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/take.cc
index 5947c7bafabeae846d7030b7558c030ac87cde97..55f748247376308d69fab014fb971679281dbe9d 100644
--- a/libstdc++-v3/testsuite/std/ranges/adaptors/take.cc
+++ b/libstdc++-v3/testsuite/std/ranges/adaptors/take.cc
@@ -100,6 +100,23 @@ test05()
   b = ranges::end(v);
 }
 
+template<auto take = views::take>
+void
+test06()
+{
+  // Verify SFINAE behavior.
+  extern int x[5];
+  int* n = 0;
+  static_assert(!requires { take(); });
+  static_assert(!requires { take(x, n, n); });
+  static_assert(!requires { take(x, n); });
+  static_assert(!requires { take(n)(x); });
+  static_assert(!requires { x | (take(n) | views::all); });
+  static_assert(!requires { (take(n) | views::all)(x); });
+  static_assert(!requires { take | views::all; });
+  static_assert(!requires { views::all | take; });
+}
+
 int
 main()
 {
@@ -108,4 +125,5 @@ main()
   test03();
   test04();
   test05();
+  test06();
 }
diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/take_while.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/take_while.cc
index ff377e578c4aa0636ebd1c663db287dac0af20db..1ab8df3bc62b266c308e9f1e5c4b226aead34609 100644
--- a/libstdc++-v3/testsuite/std/ranges/adaptors/take_while.cc
+++ b/libstdc++-v3/testsuite/std/ranges/adaptors/take_while.cc
@@ -79,6 +79,23 @@ test04()
   static_assert(!ranges::range<decltype(v) const>);
 }
 
+template<auto take_while = views::take_while>
+void
+test05()
+{
+  // Verify SFINAE behavior.
+  extern int x[5];
+  auto p = [] (int*) { return true; };
+  static_assert(!requires { take_while(); });
+  static_assert(!requires { take_while(x, p, p); });
+  static_assert(!requires { take_while(x, p); });
+  static_assert(!requires { take_while(p)(x); });
+  static_assert(!requires { x | (take_while(p) | views::all); });
+  static_assert(!requires { (take_while(p) | views::all)(x); });
+  static_assert(!requires { take_while | views::all; });
+  static_assert(!requires { views::all | take_while; });
+}
+
 int
 main()
 {
@@ -86,4 +103,5 @@ main()
   test02();
   test03();
   test04();
+  test05();
 }
diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc
index 4e7e7ba0a672e0f978d8bf508c5bac3da5965edc..ab2f28a2111683b2769e49680d214238c310edd3 100644
--- a/libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc
+++ b/libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc
@@ -145,6 +145,33 @@ test06()
   VERIFY( (next(b_const, 2) - b_const) == 2 );
 }
 
+void
+test07()
+{
+  int x[] = {1,2,3,4,5};
+  auto v1 = views::transform([] (auto& x) { return &x; });
+  auto v2 = views::transform([] (auto x) { return *x; });
+  auto v = x | (v1 | v2);
+  VERIFY( ranges::equal(v, x) );
+}
+
+template<auto transform = views::transform>
+void
+test08()
+{
+  // Verify SFINAE behavior.
+  extern int x[5];
+  auto f = [] (int* e) { return e; };
+  static_assert(!requires { transform(); });
+  static_assert(!requires { transform(x, f, f); });
+  static_assert(!requires { transform(x, f); });
+  static_assert(!requires { transform(f)(x); });
+  static_assert(!requires { x | (transform(f) | views::all); });
+  static_assert(!requires { (transform(f) | views::all)(x); });
+  static_assert(!requires { transform | views::all; });
+  static_assert(!requires { views::all | transform; });
+}
+
 int
 main()
 {
@@ -154,4 +181,6 @@ main()
   test04();
   test05();
   test06();
+  test07();
+  test08();
 }