view::all
include\range\v3\view\all.hpp
struct all_fn : pipeable<all_fn>
{
private:
/// If it's a view already, pass it though.
template<typename T>
static auto from_range_(T && t, std::true_type, detail::ignore_t,
detail::ignore_t)
{
return static_cast<T &&>(t);
}
/// If it is container-like, turn it into a view, being careful
/// to preserve the Sized-ness of the range.
template<typename T>
static auto from_range_(T && t, std::false_type, std::true_type,
detail::ignore_t)
{
return ranges::view::ref(t);
}
/// Not a view and not an lvalue? If it's a ForwardingRange_, then
/// return a subrange holding the range's begin/end.
template<typename T>
static auto from_range_(T && t, std::false_type, std::false_type,
std::true_type)
{
return make_subrange(static_cast<T &&>(t));
}
public:
template<typename T>
auto CPP_fun(operator())(T && t)(const requires ViewableRange<T>)
{
return all_fn::from_range_(static_cast<T &&>(t),
meta::bool_<View<uncvref_t<T>>>{},
std::is_lvalue_reference<T>{},
meta::bool_<ForwardingRange_<T>>{});
}
template<typename T>
RANGES_DEPRECATED("Passing a reference_wrapper to view::all is deprecated.")
auto operator()(std::reference_wrapper<T> ref) const
-> CPP_ret(ref_view<T>)( //
requires Range<T &>)
{
return ranges::view::ref(ref.get());
}
};
分析all的实现,他的思路是operator()(T && t)调用重载了的all_fn::from_range_: 通过meta::bool_<View<uncvref_t>>{}和std::is_lvalue_reference{}实现重载。
深入理解这个函数的几个障碍是:
- detail::ignore_t
- ranges::view::ref
- make_subrange
- pipeable<all_fn>的实现
- ViewableRange和requires Range<T &>的要求
ignore_t
include\range\v3\range_fwd.hpp
struct ignore_t
{
ignore_t() = default;
template<typename T>
constexpr ignore_t(T &&) noexcept
{}
template<typename T>
constexpr ignore_t const & operator=(T &&) const noexcept
{
return *this;
}
};
ignore_t实现了三个构造函数:1. 默认构造函数,2. 移动构造函数:允许任何类型转变为ignore_t; 3. 移动赋值函数:允许任何类型赋值为ignore_t. 这里的参数并没有指定名字。 2和3并没有指定参数的名字,所以,这个ignore_t允许把任何 类型赋值给他。
ranges::view::ref
struct ref_fn
{
template<typename Rng>
constexpr auto operator()(Rng & rng) const noexcept
-> CPP_ret(ref_view<Rng>)( //
requires Range<Rng>)
{
return ref_view<Rng>(rng);
}
template<typename Rng>
void operator()(Rng const && rng) const = delete;
};
/// \relates const_fn
/// \ingroup group-views
RANGES_INLINE_VARIABLE(view<ref_fn>, ref)
返回的是ref_view, 所以,主要看ref_view的实现:
ref_view
/// \cond
namespace _ref_view_
{
struct adl_hook
{};
template<typename Rng>
constexpr iterator_t<Rng> begin(ref_view<Rng> && rng) noexcept(
noexcept(rng.begin()))
{
return rng.begin();
}
template<typename Rng>
constexpr iterator_t<Rng> begin(ref_view<Rng> const && rng) noexcept(
noexcept(rng.begin()))
{
return rng.begin();
}
template<typename Rng>
constexpr sentinel_t<Rng> end(ref_view<Rng> && rng) noexcept(noexcept(rng.end()))
{
return rng.end();
}
template<typename Rng>
constexpr sentinel_t<Rng> end(ref_view<Rng> const && rng) noexcept(
noexcept(rng.end()))
{
return rng.end();
}
} // namespace _ref_view_
/// \endcond
_ref_view_实现了对range begin和end的调用,相当于一个proxy类。
ref_view
/// \addtogroup group-views
/// @{
template<typename Rng>
struct ref_view
: view_interface<ref_view<Rng>, range_cardinality<Rng>::value>
, private _ref_view_::adl_hook
{
}
ref依赖于ref_view,而ref_view的实现依赖于view_interface. 所以,要先分析一下view interface。