146 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++14, c++1710 11// std::views::transform12 13#include <ranges>14 15#include <cassert>16#include <concepts>17#include <type_traits>18#include <utility>19 20#include "test_macros.h"21#include "test_range.h"22#include "types.h"23 24struct NonCopyableFunction {25 NonCopyableFunction(NonCopyableFunction const&) = delete;26 template <class T>27 constexpr T operator()(T x) const { return x; }28};29 30constexpr bool test() {31 int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7};32 33 // Test `views::transform(f)(v)`34 {35 {36 using Result = std::ranges::transform_view<MoveOnlyView, PlusOne>;37 std::same_as<Result> auto result = std::views::transform(PlusOne{})(MoveOnlyView{buff});38 assert(result.begin().base() == buff);39 assert(result[0] == 1);40 assert(result[1] == 2);41 assert(result[2] == 3);42 }43 {44 auto const partial = std::views::transform(PlusOne{});45 using Result = std::ranges::transform_view<MoveOnlyView, PlusOne>;46 std::same_as<Result> auto result = partial(MoveOnlyView{buff});47 assert(result.begin().base() == buff);48 assert(result[0] == 1);49 assert(result[1] == 2);50 assert(result[2] == 3);51 }52 }53 54 // Test `v | views::transform(f)`55 {56 {57 using Result = std::ranges::transform_view<MoveOnlyView, PlusOne>;58 std::same_as<Result> auto result = MoveOnlyView{buff} | std::views::transform(PlusOne{});59 assert(result.begin().base() == buff);60 assert(result[0] == 1);61 assert(result[1] == 2);62 assert(result[2] == 3);63 }64 {65 auto const partial = std::views::transform(PlusOne{});66 using Result = std::ranges::transform_view<MoveOnlyView, PlusOne>;67 std::same_as<Result> auto result = MoveOnlyView{buff} | partial;68 assert(result.begin().base() == buff);69 assert(result[0] == 1);70 assert(result[1] == 2);71 assert(result[2] == 3);72 }73 }74 75 // Test `views::transform(v, f)`76 {77 using Result = std::ranges::transform_view<MoveOnlyView, PlusOne>;78 std::same_as<Result> auto result = std::views::transform(MoveOnlyView{buff}, PlusOne{});79 assert(result.begin().base() == buff);80 assert(result[0] == 1);81 assert(result[1] == 2);82 assert(result[2] == 3);83 }84 85 // Test that one can call std::views::transform with arbitrary stuff, as long as we86 // don't try to actually complete the call by passing it a range.87 //88 // That makes no sense and we can't do anything with the result, but it's valid.89 {90 struct X { };91 auto partial = std::views::transform(X{});92 (void)partial;93 }94 95 // Test `adaptor | views::transform(f)`96 {97 {98 using Result = std::ranges::transform_view<std::ranges::transform_view<MoveOnlyView, PlusOne>, TimesTwo>;99 std::same_as<Result> auto result = MoveOnlyView{buff} | std::views::transform(PlusOne{}) | std::views::transform(TimesTwo{});100 assert(result.begin().base().base() == buff);101 assert(result[0] == 2);102 assert(result[1] == 4);103 assert(result[2] == 6);104 }105 {106 auto const partial = std::views::transform(PlusOne{}) | std::views::transform(TimesTwo{});107 using Result = std::ranges::transform_view<std::ranges::transform_view<MoveOnlyView, PlusOne>, TimesTwo>;108 std::same_as<Result> auto result = MoveOnlyView{buff} | partial;109 assert(result.begin().base().base() == buff);110 assert(result[0] == 2);111 assert(result[1] == 4);112 assert(result[2] == 6);113 }114 }115 116 // Test SFINAE friendliness117 {118 struct NotAView { };119 struct NotInvocable { };120 121 static_assert(!CanBePiped<MoveOnlyView, decltype(std::views::transform)>);122 static_assert( CanBePiped<MoveOnlyView, decltype(std::views::transform(PlusOne{}))>);123 static_assert(!CanBePiped<NotAView, decltype(std::views::transform(PlusOne{}))>);124 static_assert(!CanBePiped<MoveOnlyView, decltype(std::views::transform(NotInvocable{}))>);125 126 static_assert(!std::is_invocable_v<decltype(std::views::transform)>);127 static_assert(!std::is_invocable_v<decltype(std::views::transform), PlusOne, MoveOnlyView>);128 static_assert( std::is_invocable_v<decltype(std::views::transform), MoveOnlyView, PlusOne>);129 static_assert(!std::is_invocable_v<decltype(std::views::transform), MoveOnlyView, PlusOne, PlusOne>);130 static_assert(!std::is_invocable_v<decltype(std::views::transform), NonCopyableFunction>);131 }132 133 {134 static_assert(std::is_same_v<decltype(std::ranges::views::transform), decltype(std::views::transform)>);135 }136 137 return true;138}139 140int main(int, char**) {141 test();142 static_assert(test());143 144 return 0;145}146