//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14, c++17 // UNSUPPORTED: libcpp-has-no-incomplete-ranges // std::views::transform #include #include #include #include #include #include "test_macros.h" #include "types.h" template concept CanBePiped = requires (View&& view, T&& t) { { std::forward(view) | std::forward(t) }; }; struct NonCopyableFunction { NonCopyableFunction(NonCopyableFunction const&) = delete; template constexpr T operator()(T x) const { return x; } }; constexpr bool test() { int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7}; // Test `views::transform(f)(v)` { { using Result = std::ranges::transform_view; std::same_as auto result = std::views::transform(PlusOne{})(MoveOnlyView{buff}); assert(result.begin().base() == buff); assert(result[0] == 1); assert(result[1] == 2); assert(result[2] == 3); } { auto const partial = std::views::transform(PlusOne{}); using Result = std::ranges::transform_view; std::same_as auto result = partial(MoveOnlyView{buff}); assert(result.begin().base() == buff); assert(result[0] == 1); assert(result[1] == 2); assert(result[2] == 3); } } // Test `v | views::transform(f)` { { using Result = std::ranges::transform_view; std::same_as auto result = MoveOnlyView{buff} | std::views::transform(PlusOne{}); assert(result.begin().base() == buff); assert(result[0] == 1); assert(result[1] == 2); assert(result[2] == 3); } { auto const partial = std::views::transform(PlusOne{}); using Result = std::ranges::transform_view; std::same_as auto result = MoveOnlyView{buff} | partial; assert(result.begin().base() == buff); assert(result[0] == 1); assert(result[1] == 2); assert(result[2] == 3); } } // Test `views::transform(v, f)` { using Result = std::ranges::transform_view; std::same_as auto result = std::views::transform(MoveOnlyView{buff}, PlusOne{}); assert(result.begin().base() == buff); assert(result[0] == 1); assert(result[1] == 2); assert(result[2] == 3); } // Test that one can call std::views::transform with arbitrary stuff, as long as we // don't try to actually complete the call by passing it a range. // // That makes no sense and we can't do anything with the result, but it's valid. { struct X { }; auto partial = std::views::transform(X{}); (void)partial; } // Test `adaptor | views::transform(f)` { { using Result = std::ranges::transform_view, TimesTwo>; std::same_as auto result = MoveOnlyView{buff} | std::views::transform(PlusOne{}) | std::views::transform(TimesTwo{}); assert(result.begin().base().base() == buff); assert(result[0] == 2); assert(result[1] == 4); assert(result[2] == 6); } { auto const partial = std::views::transform(PlusOne{}) | std::views::transform(TimesTwo{}); using Result = std::ranges::transform_view, TimesTwo>; std::same_as auto result = MoveOnlyView{buff} | partial; assert(result.begin().base().base() == buff); assert(result[0] == 2); assert(result[1] == 4); assert(result[2] == 6); } } // Test SFINAE friendliness { struct NotAView { }; struct NotInvocable { }; static_assert(!CanBePiped); static_assert( CanBePiped); static_assert(!CanBePiped); static_assert(!CanBePiped); static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert( std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); } { static_assert(std::is_same_v); } return true; } int main(int, char**) { test(); static_assert(test()); return 0; }