#ifndef RANGE_HELPERS_INL_H_ #error "Direct inclusion of this file is not allowed, include range_helpers.h" // For the sake of sane code completion. #include "range_helpers.h" #endif namespace NYT { namespace NDetail { //////////////////////////////////////////////////////////////////////////////// template struct TAppendTo { }; template requires requires (TContainer container, typename TContainer::value_type value) { container.push_back(value); } struct TAppendTo { template static void Append(TContainer& container, TValue&& value) { container.push_back(std::forward(value)); } }; template requires requires (TContainer container, typename TContainer::value_type value) { container.insert(value); } struct TAppendTo { template static void Append(TContainer& container, TValue&& value) { container.insert(std::forward(value)); } }; //////////////////////////////////////////////////////////////////////////////// template struct TRangeTo { }; template requires requires (TContainer container, typename TContainer::value_type value) { TAppendTo::Append(container, value); } struct TRangeTo { template static auto ToContainer(TRange&& range) { TContainer container; if constexpr (requires { std::ranges::size(range); } && requires { container.reserve(std::declval()); }) { container.reserve(std::ranges::size(range)); } for (auto&& element : range) { TAppendTo::Append(container, std::forward(element)); } return container; } template static auto StaticRangeToContainer(TValues... values) { TContainer container; if constexpr (requires { container.reserve(std::declval()); }) { container.reserve(sizeof...(TValues)); } (TAppendTo::Append(container, std::forward(values)), ...); return container; } }; //////////////////////////////////////////////////////////////////////////////// } // namespace NDetail //////////////////////////////////////////////////////////////////////////////// template auto ZipMutable(TContainers&&... containers) { return Zip(std::ranges::views::transform(containers, [] (T&& t) { return &t; })...); } template auto RangeTo(TRange&& range) { return NDetail::TRangeTo::template ToContainer(std::forward(range)); } template constexpr auto RangeTo() { return NDetail::TRangeToTag(); } template auto operator|(TRange&& range, NDetail::TRangeToTag) { return RangeTo(std::forward(range)); } template auto TransformRangeTo(TRange&& range, TTransformFunction&& function) { return RangeTo(std::ranges::views::transform( std::forward(range), std::forward(function))); } template requires (std::constructible_from && ...) TContainer StaticRangeTo(TValues... values) { return NDetail::TRangeTo::template StaticRangeToContainer(std::forward(values)...); } template struct TStaticRange { public: explicit TStaticRange(TValues... values) : Tuple_(std::forward(values)...) { } template operator TContainer() && { return std::apply(&StaticRangeTo, std::move(Tuple_)); } private: std::tuple Tuple_; }; template auto FoldRange(TRange&& range, TOperation operation, TProjection projection) { auto iter = range.begin(); if (iter == range.end()) { return std::remove_cvref_t{}; } auto accumulator = std::invoke(projection, *iter); for (++iter; iter != range.end(); ++iter) { accumulator = std::invoke(operation, accumulator, std::invoke(projection, *iter)); } return accumulator; } //////////////////////////////////////////////////////////////////////////////// } // namespace NYT