11e77b396SNikolas Klauser //===----------------------------------------------------------------------===//
21e77b396SNikolas Klauser //
31e77b396SNikolas Klauser // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
41e77b396SNikolas Klauser // See https://llvm.org/LICENSE.txt for license information.
51e77b396SNikolas Klauser // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61e77b396SNikolas Klauser //
71e77b396SNikolas Klauser //===----------------------------------------------------------------------===//
81e77b396SNikolas Klauser
91e77b396SNikolas Klauser // UNSUPPORTED: c++03, c++11, c++14, c++17
101e77b396SNikolas Klauser
111e77b396SNikolas Klauser // template <class I1, class I2>
121e77b396SNikolas Klauser // struct in_fun_result;
131e77b396SNikolas Klauser
141e77b396SNikolas Klauser #include <algorithm>
151e77b396SNikolas Klauser #include <cassert>
161e77b396SNikolas Klauser #include <type_traits>
171e77b396SNikolas Klauser #include <utility>
181e77b396SNikolas Klauser
191e77b396SNikolas Klauser #include "MoveOnly.h"
201e77b396SNikolas Klauser
211e77b396SNikolas Klauser struct A {
221e77b396SNikolas Klauser explicit A(int);
231e77b396SNikolas Klauser };
241e77b396SNikolas Klauser // no implicit conversion
251e77b396SNikolas Klauser static_assert(!std::is_constructible_v<std::ranges::in_fun_result<A, A>, std::ranges::in_fun_result<int, int>>);
261e77b396SNikolas Klauser
271e77b396SNikolas Klauser struct B {
281e77b396SNikolas Klauser B(int);
291e77b396SNikolas Klauser };
301e77b396SNikolas Klauser // implicit conversion
311e77b396SNikolas Klauser static_assert(std::is_constructible_v<std::ranges::in_fun_result<B, B>, std::ranges::in_fun_result<int, int>>);
321e77b396SNikolas Klauser static_assert(std::is_constructible_v<std::ranges::in_fun_result<B, B>, std::ranges::in_fun_result<int, int>&>);
331e77b396SNikolas Klauser static_assert(std::is_constructible_v<std::ranges::in_fun_result<B, B>, const std::ranges::in_fun_result<int, int>>);
341e77b396SNikolas Klauser static_assert(std::is_constructible_v<std::ranges::in_fun_result<B, B>, const std::ranges::in_fun_result<int, int>&>);
351e77b396SNikolas Klauser
361e77b396SNikolas Klauser struct C {
371e77b396SNikolas Klauser C(int&);
381e77b396SNikolas Klauser };
391e77b396SNikolas Klauser static_assert(!std::is_constructible_v<std::ranges::in_fun_result<C, C>, std::ranges::in_fun_result<int, int>&>);
401e77b396SNikolas Klauser
41e06ca312SNikolas Klauser // has to be convertible via const&
421e77b396SNikolas Klauser static_assert(std::is_convertible_v<std::ranges::in_fun_result<int, int>&, std::ranges::in_fun_result<long, long>>);
431e77b396SNikolas Klauser static_assert(std::is_convertible_v<const std::ranges::in_fun_result<int, int>&, std::ranges::in_fun_result<long, long>>);
441e77b396SNikolas Klauser static_assert(std::is_convertible_v<std::ranges::in_fun_result<int, int>&&, std::ranges::in_fun_result<long, long>>);
451e77b396SNikolas Klauser static_assert(std::is_convertible_v<const std::ranges::in_fun_result<int, int>&&, std::ranges::in_fun_result<long, long>>);
461e77b396SNikolas Klauser
471e77b396SNikolas Klauser // should be move constructible
481e77b396SNikolas Klauser static_assert(std::is_move_constructible_v<std::ranges::in_fun_result<MoveOnly, int>>);
491e77b396SNikolas Klauser static_assert(std::is_move_constructible_v<std::ranges::in_fun_result<int, MoveOnly>>);
501e77b396SNikolas Klauser
51*f0ea888eSChristopher Di Bella // should not be copy constructible with move-only type
521e77b396SNikolas Klauser static_assert(!std::is_copy_constructible_v<std::ranges::in_fun_result<MoveOnly, int>>);
531e77b396SNikolas Klauser static_assert(!std::is_copy_constructible_v<std::ranges::in_fun_result<int, MoveOnly>>);
541e77b396SNikolas Klauser
551e77b396SNikolas Klauser struct NotConvertible {};
561e77b396SNikolas Klauser // conversions should not work if there is no conversion
57e06ca312SNikolas Klauser static_assert(!std::is_convertible_v<std::ranges::in_fun_result<NotConvertible, int>, std::ranges::in_fun_result<int, int>>);
58e06ca312SNikolas Klauser static_assert(!std::is_convertible_v<std::ranges::in_fun_result<int, NotConvertible>, std::ranges::in_fun_result<int, int>>);
591e77b396SNikolas Klauser
601e77b396SNikolas Klauser template <class T>
611e77b396SNikolas Klauser struct ConvertibleFrom {
ConvertibleFromConvertibleFrom621e77b396SNikolas Klauser constexpr ConvertibleFrom(T c) : content{c} {}
631e77b396SNikolas Klauser T content;
641e77b396SNikolas Klauser };
651e77b396SNikolas Klauser
test()661e77b396SNikolas Klauser constexpr bool test() {
67*f0ea888eSChristopher Di Bella // Checks that conversion operations are correct.
681e77b396SNikolas Klauser {
691e77b396SNikolas Klauser std::ranges::in_fun_result<int, double> res{10, 0.};
701e77b396SNikolas Klauser assert(res.in == 10);
711e77b396SNikolas Klauser assert(res.fun == 0.);
721e77b396SNikolas Klauser std::ranges::in_fun_result<ConvertibleFrom<int>, ConvertibleFrom<double>> res2 = res;
731e77b396SNikolas Klauser assert(res2.in.content == 10);
741e77b396SNikolas Klauser assert(res2.fun.content == 0.);
751e77b396SNikolas Klauser }
76*f0ea888eSChristopher Di Bella
77*f0ea888eSChristopher Di Bella // Checks that conversions are possible when one of the types is move-only.
781e77b396SNikolas Klauser {
791e77b396SNikolas Klauser std::ranges::in_fun_result<MoveOnly, int> res{MoveOnly{}, 2};
801e77b396SNikolas Klauser assert(res.in.get() == 1);
811e77b396SNikolas Klauser assert(res.fun == 2);
821e77b396SNikolas Klauser auto res2 = static_cast<std::ranges::in_fun_result<MoveOnly, int>>(std::move(res));
831e77b396SNikolas Klauser assert(res.in.get() == 0);
841e77b396SNikolas Klauser assert(res2.in.get() == 1);
851e77b396SNikolas Klauser assert(res2.fun == 2);
861e77b396SNikolas Klauser }
87*f0ea888eSChristopher Di Bella
88*f0ea888eSChristopher Di Bella // Checks that structured bindings get the correct values.
891e77b396SNikolas Klauser {
901e77b396SNikolas Klauser auto [in, fun] = std::ranges::in_fun_result<int, int>{1, 2};
911e77b396SNikolas Klauser assert(in == 1);
921e77b396SNikolas Klauser assert(fun == 2);
931e77b396SNikolas Klauser }
941e77b396SNikolas Klauser return true;
951e77b396SNikolas Klauser }
961e77b396SNikolas Klauser
main(int,char **)971e77b396SNikolas Klauser int main(int, char**) {
981e77b396SNikolas Klauser test();
991e77b396SNikolas Klauser static_assert(test());
1001e77b396SNikolas Klauser
1011e77b396SNikolas Klauser return 0;
1021e77b396SNikolas Klauser }
103