From 005c8634edff94206f6df378d5d37df692f0de6a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20Kr=C3=BCgler?=
+
+The expression adaptor(args...) produces a range adaptor closure object f that is a perfect forwarding
+call wrapper (
+According to the subsequent description, it can be inferred that the behavior is similar to
+std::bind_back(adaptor, args...) which also returns a perfect forwarding call wrapper.
+
+
++Every call wrapper (
) meets the Cpp17MoveConstructible and Cpp17Destructible requirements. +
+In order to conform with the specification, standard functions that return perfect forwarding call wrappers such as
+std::bind_front/back and std::not_fn all Mandates that
+(is_constructible_v<BoundArgs, Args> && ...) and
+(is_move_constructible_v<BoundArgs> && ...) are each true,
+the former condition corresponds to
++The expression adaptor(args...) is well-formed if and only if the initialization of the bound argument +entities of the result, as specified above, are all well-formed. +
+However, the latter does not have a corresponding description in <ranges>. In other words, range +adaptor objects do not explicitly indicate that the bound argument must be move-constructible. +This results in implementation divergence for some uncommon types (demo): +
+
+#include <ranges>
+#include <string_view>
+
+constexpr struct WeirdFive {
+ WeirdFive() = default;
+ WeirdFive(const WeirdFive&) = default;
+ constexpr operator int() const { return 5; }
+
+ WeirdFive(WeirdFive&&) = delete;
+} five;
+
+constexpr std::string_view sv{"hello"};
+static_assert(sv == std::views::take(five)(sv)); // libstdc++/libc++ reject, MSVC-STL accepts
+
++Above, libstdc++ always moves arguments into internal members, which leads to hard errors in the member initializer list; +libc++ uses std::bind_back for argument binding, which also leads to hard errors in the function body as the +former requires arguments to be move-constructible; MSVC-STL is the most compliant with current wording. +
+ + +