160 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// std::views::zip_transform12 13#include <ranges>14 15#include <algorithm>16#include <array>17#include <cassert>18#include <functional>19#include <type_traits>20#include <vector>21 22#include "types.h"23 24struct NotMoveConstructible {25 NotMoveConstructible() = default;26 NotMoveConstructible(NotMoveConstructible&&) = delete;27 int operator()() const { return 5; }28};29 30struct NotCopyConstructible {31 NotCopyConstructible() = default;32 NotCopyConstructible(NotCopyConstructible&&) = default;33 NotCopyConstructible(const NotCopyConstructible&) = delete;34 int operator()() const { return 5; }35};36 37struct NotInvocable {};38 39template <class... Args>40struct Invocable {41 int operator()(Args...) const { return 5; }42};43 44struct ReturnNotObject {45 void operator()() const {}46};47 48// LWG3773 views::zip_transform still requires F to be copy_constructible when empty pack49static_assert(std::is_invocable_v<decltype((std::views::zip_transform)), NotCopyConstructible>);50 51static_assert(!std::is_invocable_v<decltype((std::views::zip_transform))>);52static_assert(!std::is_invocable_v<decltype((std::views::zip_transform)), NotMoveConstructible>);53static_assert(!std::is_invocable_v<decltype((std::views::zip_transform)), NotInvocable>);54static_assert(std::is_invocable_v<decltype((std::views::zip_transform)), Invocable<>>);55static_assert(!std::is_invocable_v<decltype((std::views::zip_transform)), ReturnNotObject>);56 57static_assert(std::is_invocable_v<decltype((std::views::zip_transform)), //58 Invocable<int>, //59 std::ranges::iota_view<int, int>>);60static_assert(!std::is_invocable_v<decltype((std::views::zip_transform)), //61 Invocable<>, //62 std::ranges::iota_view<int, int>>);63static_assert(!std::is_invocable_v<decltype((std::views::zip_transform)),64 Invocable<int>,65 std::ranges::iota_view<int, int>,66 std::ranges::iota_view<int, int>>);67static_assert(std::is_invocable_v<decltype((std::views::zip_transform)),68 Invocable<int, int>,69 std::ranges::iota_view<int, int>,70 std::ranges::iota_view<int, int>>);71 72constexpr bool test() {73 {74 // zip_transform function with no ranges75 auto v = std::views::zip_transform(Invocable<>{});76 assert(std::ranges::empty(v));77 static_assert(std::is_same_v<decltype(v), std::ranges::empty_view<int>>);78 }79 80 {81 // zip_transform views82 int buffer1[] = {1, 2, 3, 4, 5, 6, 7, 8};83 int buffer2[] = {9, 10, 11, 12};84 auto view1 = std::views::all(buffer1);85 auto view2 = std::views::all(buffer2);86 std::same_as<std::ranges::zip_transform_view<std::plus<>, decltype(view1), decltype(view2)>> decltype(auto) v =87 std::views::zip_transform(std::plus{}, buffer1, buffer2);88 assert(std::ranges::size(v) == 4);89 auto expected = {10, 12, 14, 16};90 assert(std::ranges::equal(v, expected));91 static_assert(std::is_same_v<std::ranges::range_reference_t<decltype(v)>, int>);92 }93 94 {95 // zip_transform a viewable range96 std::array a{1, 2, 3};97 auto id = [](auto& x) -> decltype(auto) { return (x); };98 std::same_as<99 std::ranges::zip_transform_view<decltype(id), std::ranges::ref_view<std::array<int, 3>>>> decltype(auto) v =100 std::views::zip_transform(id, a);101 assert(&v[0] == &a[0]);102 static_assert(std::is_same_v<std::ranges::range_reference_t<decltype(v)>, int&>);103 }104 105 int buffer[] = {1, 2, 3};106 {107 // one range108 auto v = std::views::zip_transform(MakeTuple{}, SimpleCommon{buffer});109 assert(std::ranges::equal(v, std::vector{std::tuple(1), std::tuple(2), std::tuple(3)}));110 }111 112 {113 // two ranges114 auto v = std::views::zip_transform(GetFirst{}, SimpleCommon{buffer}, std::views::iota(0));115 assert(std::ranges::equal(v, std::vector{1, 2, 3}));116 }117 118 {119 // three ranges120 auto v = std::views::zip_transform(Tie{}, SimpleCommon{buffer}, SimpleCommon{buffer}, std::ranges::single_view(2.));121 assert(std::ranges::equal(v, std::vector{std::tuple(1, 1, 2.0)}));122 }123 124 {125 // single empty range126 auto v = std::views::zip_transform(MakeTuple{}, std::ranges::empty_view<int>());127 assert(std::ranges::empty(v));128 }129 130 {131 // empty range at the beginning132 auto v = std::views::zip_transform(133 MakeTuple{}, std::ranges::empty_view<int>(), SimpleCommon{buffer}, SimpleCommon{buffer});134 assert(std::ranges::empty(v));135 }136 137 {138 // empty range in the middle139 auto v = std::views::zip_transform(140 MakeTuple{}, SimpleCommon{buffer}, std::ranges::empty_view<int>(), SimpleCommon{buffer});141 assert(std::ranges::empty(v));142 }143 144 {145 // empty range at the end146 auto v = std::views::zip_transform(147 MakeTuple{}, SimpleCommon{buffer}, SimpleCommon{buffer}, std::ranges::empty_view<int>());148 assert(std::ranges::empty(v));149 }150 151 return true;152}153 154int main(int, char**) {155 test();156 static_assert(test());157 158 return 0;159}160