103 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// template <class I1, class I2>12// struct in_fun_result;13 14#include <algorithm>15#include <cassert>16#include <type_traits>17#include <utility>18 19#include "MoveOnly.h"20 21struct A {22 explicit A(int);23};24// no implicit conversion25static_assert(!std::is_constructible_v<std::ranges::in_fun_result<A, A>, std::ranges::in_fun_result<int, int>>);26 27struct B {28 B(int);29};30// implicit conversion31static_assert(std::is_constructible_v<std::ranges::in_fun_result<B, B>, std::ranges::in_fun_result<int, int>>);32static_assert(std::is_constructible_v<std::ranges::in_fun_result<B, B>, std::ranges::in_fun_result<int, int>&>);33static_assert(std::is_constructible_v<std::ranges::in_fun_result<B, B>, const std::ranges::in_fun_result<int, int>>);34static_assert(std::is_constructible_v<std::ranges::in_fun_result<B, B>, const std::ranges::in_fun_result<int, int>&>);35 36struct C {37 C(int&);38};39static_assert(!std::is_constructible_v<std::ranges::in_fun_result<C, C>, std::ranges::in_fun_result<int, int>&>);40 41// has to be convertible via const&42static_assert(std::is_convertible_v<std::ranges::in_fun_result<int, int>&, std::ranges::in_fun_result<long, long>>);43static_assert(std::is_convertible_v<const std::ranges::in_fun_result<int, int>&, std::ranges::in_fun_result<long, long>>);44static_assert(std::is_convertible_v<std::ranges::in_fun_result<int, int>&&, std::ranges::in_fun_result<long, long>>);45static_assert(std::is_convertible_v<const std::ranges::in_fun_result<int, int>&&, std::ranges::in_fun_result<long, long>>);46 47// should be move constructible48static_assert(std::is_move_constructible_v<std::ranges::in_fun_result<MoveOnly, int>>);49static_assert(std::is_move_constructible_v<std::ranges::in_fun_result<int, MoveOnly>>);50 51// should not be copy constructible with move-only type52static_assert(!std::is_copy_constructible_v<std::ranges::in_fun_result<MoveOnly, int>>);53static_assert(!std::is_copy_constructible_v<std::ranges::in_fun_result<int, MoveOnly>>);54 55struct NotConvertible {};56// conversions should not work if there is no conversion57static_assert(!std::is_convertible_v<std::ranges::in_fun_result<NotConvertible, int>, std::ranges::in_fun_result<int, int>>);58static_assert(!std::is_convertible_v<std::ranges::in_fun_result<int, NotConvertible>, std::ranges::in_fun_result<int, int>>);59 60template <class T>61struct ConvertibleFrom {62 constexpr ConvertibleFrom(T c) : content{c} {}63 T content;64};65 66constexpr bool test() {67 // Checks that conversion operations are correct.68 {69 std::ranges::in_fun_result<int, double> res{10, 0.};70 assert(res.in == 10);71 assert(res.fun == 0.);72 std::ranges::in_fun_result<ConvertibleFrom<int>, ConvertibleFrom<double>> res2 = res;73 assert(res2.in.content == 10);74 assert(res2.fun.content == 0.);75 }76 77 // Checks that conversions are possible when one of the types is move-only.78 {79 std::ranges::in_fun_result<MoveOnly, int> res{MoveOnly{}, 2};80 assert(res.in.get() == 1);81 assert(res.fun == 2);82 auto res2 = static_cast<std::ranges::in_fun_result<MoveOnly, int>>(std::move(res));83 assert(res.in.get() == 0);84 assert(res2.in.get() == 1);85 assert(res2.fun == 2);86 }87 88 // Checks that structured bindings get the correct values.89 {90 auto [in, fun] = std::ranges::in_fun_result<int, int>{1, 2};91 assert(in == 1);92 assert(fun == 2);93 }94 return true;95}96 97int main(int, char**) {98 test();99 static_assert(test());100 101 return 0;102}103