145 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++17, c++2010 11// constexpr explicit zip_transform_view(F, Views...)12 13#include <algorithm>14#include <ranges>15#include <vector>16 17#include "types.h"18 19struct Fn {20 int operator()(auto&&...) const { return 5; }21};22 23template <class T, class... Args>24concept IsImplicitlyConstructible = requires(T val, Args... args) { val = {std::forward<Args>(args)...}; };25 26// test constructor is explicit27static_assert(std::constructible_from<std::ranges::zip_transform_view<Fn, IntView>, Fn, IntView>);28static_assert(!IsImplicitlyConstructible<std::ranges::zip_transform_view<Fn, IntView>, Fn, IntView>);29 30static_assert(std::constructible_from<std::ranges::zip_transform_view<Fn, IntView, IntView>, Fn, IntView, IntView>);31static_assert(!IsImplicitlyConstructible<std::ranges::zip_transform_view<Fn, IntView, IntView>, Fn, IntView, IntView>);32 33struct MoveAwareView : std::ranges::view_base {34 int moves = 0;35 constexpr MoveAwareView() = default;36 constexpr MoveAwareView(MoveAwareView&& other) : moves(other.moves + 1) { other.moves = 1; }37 constexpr MoveAwareView& operator=(MoveAwareView&& other) {38 moves = other.moves + 1;39 other.moves = 0;40 return *this;41 }42 constexpr const int* begin() const { return &moves; }43 constexpr const int* end() const { return &moves + 1; }44};45 46template <class View1, class View2>47constexpr void constructorTest(auto&& buffer1, auto&& buffer2) {48 std::ranges::zip_transform_view v{MakeTuple{}, View1{buffer1}, View2{buffer2}};49 auto [i, j] = *v.begin();50 assert(i == buffer1[0]);51 assert(j == buffer2[0]);52};53 54constexpr bool test() {55 int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8};56 int buffer2[4] = {9, 8, 7, 6};57 58 {59 // one range60 std::ranges::zip_transform_view v(MakeTuple{}, SimpleCommon{buffer2});61 assert(std::ranges::equal(v, std::vector{std::tuple(9), std::tuple(8), std::tuple(7), std::tuple(6)}));62 }63 64 {65 // two ranges66 std::ranges::zip_transform_view v(GetFirst{}, SimpleCommon{buffer}, std::views::iota(0));67 assert(std::ranges::equal(v, std::vector{1, 2, 3, 4, 5, 6, 7, 8}));68 }69 70 {71 // three ranges72 std::ranges::zip_transform_view v(Tie{}, SimpleCommon{buffer}, SimpleCommon{buffer2}, std::ranges::single_view(2.));73 assert(std::ranges::equal(v, std::vector{std::tuple(1, 9, 2.0)}));74 }75 76 {77 // single empty range78 std::ranges::zip_transform_view v(MakeTuple{}, std::ranges::empty_view<int>());79 assert(std::ranges::empty(v));80 }81 82 {83 // empty range at the beginning84 std::ranges::zip_transform_view v(85 MakeTuple{}, std::ranges::empty_view<int>(), SimpleCommon{buffer}, SimpleCommon{buffer});86 assert(std::ranges::empty(v));87 }88 89 {90 // empty range in the middle91 std::ranges::zip_transform_view v(92 MakeTuple{}, SimpleCommon{buffer}, std::ranges::empty_view<int>(), SimpleCommon{buffer});93 assert(std::ranges::empty(v));94 }95 96 {97 // empty range at the end98 std::ranges::zip_transform_view v(99 MakeTuple{}, SimpleCommon{buffer}, SimpleCommon{buffer}, std::ranges::empty_view<int>());100 assert(std::ranges::empty(v));101 }102 {103 // constructor from views104 std::ranges::zip_transform_view v(105 MakeTuple{}, SizedRandomAccessView{buffer}, std::views::iota(0), std::ranges::single_view(2.));106 auto [i, j, k] = *v.begin();107 assert(i == 1);108 assert(j == 0);109 assert(k == 2.0);110 }111 112 {113 // arguments are moved once114 MoveAwareView mv;115 std::ranges::zip_transform_view v{MakeTuple{}, std::move(mv), MoveAwareView{}};116 auto [numMoves1, numMoves2] = *v.begin();117 assert(numMoves1 == 3); // one move from the local variable to parameter, one move from parameter to member118 assert(numMoves2 == 2);119 }120 121 // input and forward122 {123 constructorTest<InputCommonView, ForwardSizedView>(buffer, buffer2);124 }125 126 // bidi and random_access127 {128 constructorTest<BidiCommonView, SizedRandomAccessView>(buffer, buffer2);129 }130 131 // contiguous132 {133 constructorTest<ContiguousCommonView, ContiguousCommonView>(buffer, buffer2);134 }135 136 return true;137}138 139int main(int, char**) {140 test();141 static_assert(test());142 143 return 0;144}145