#pragma once #include "CoreTypes.h" #include "Range/View.h" #include "Range/Utility.h" #include "Range/AllView.h" #include "Templates/Utility.h" #include "Range/TransformView.h" #include "TypeTraits/TypeTraits.h" NAMESPACE_REDCRAFT_BEGIN NAMESPACE_MODULE_BEGIN(Redcraft) NAMESPACE_MODULE_BEGIN(Utility) /** A concept specifies a container that can reserve size. */ template concept CReservableContainer = CSizedRange && requires (C& Container, size_t N) { Container.Reserve(N); { Container.Max() } -> CSameAs; }; /** A concept specifies a container that can append elements. */ template concept CAppendableContainer = requires (C& Container, Ref&& Reference) { requires ( requires { Container.EmplaceBack (Forward(Reference)); } || requires { Container.PushBack (Forward(Reference)); } || requires { Container.Emplace(Container.End(), Forward(Reference)); } || requires { Container.Insert (Container.End(), Forward(Reference)); } ); }; NAMESPACE_BEGIN(Range) /** Constructs a non-view object from the elements of the range. */ template requires (!CView) NODISCARD FORCEINLINE constexpr auto To(R&& Range, Ts&&... Args) { if constexpr (!CInputRange || CConvertibleTo, TRangeElement>) { if constexpr (CConstructibleFrom) { return C(Forward(Range), Forward(Args)...); } else if constexpr (CCommonRange && CInputRange && CConstructibleFrom, TRangeSentinel, Ts...>) { return C(Range::Begin(Range), Range::End(Range), Forward(Args)...); } else if constexpr (CConstructibleFrom && CAppendableContainer>) { C Result(Forward(Args)...); if constexpr (CSizedRange && CReservableContainer) { Result.Reserve(Range::Num(Range)); } for (TRangeReference Element : Range) { if constexpr (requires { Result.EmplaceBack(DeclVal>()); }) { Result.EmplaceBack(Forward>(Element)); } else if constexpr (requires { Result.PushBack(DeclVal>()); }) { Result.PushBack(Forward>(Element)); } else if constexpr (requires { Result.Emplace(Result.End(), DeclVal>()); }) { Result.Emplace(Result.End(), Forward>(Element)); } else /* if constexpr (requires { Result.Insert(Result.End(), DeclVal>()); }) */ { Result.Insert(Result.End(), Forward>(Element)); } } return Result; } else static_assert(sizeof(C) == -1, "The container type is not constructible from a range"); } else { if constexpr (CInputRange>) { return Range::To(Range::All(Range) | Range::Transform([](T&& Element) { return Range::To>(Forward(Element)); }), Forward(Args)...); } else static_assert(sizeof(C) == -1, "The container type is not constructible from a range"); } } /** Constructs a non-view object from the elements of the range. */ template