110 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// template <class I, class T>12// struct in_value_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_value_result<A, A>, std::ranges::in_value_result<int, int>>);26 27struct B {28 B(int);29};30// implicit conversion31static_assert(std::is_constructible_v<std::ranges::in_value_result<B, B>, std::ranges::in_value_result<int, int>>);32static_assert(std::is_constructible_v<std::ranges::in_value_result<B, B>, std::ranges::in_value_result<int, int>&>);33static_assert(34 std::is_constructible_v<std::ranges::in_value_result<B, B>, const std::ranges::in_value_result<int, int>>);35static_assert(36 std::is_constructible_v<std::ranges::in_value_result<B, B>, const std::ranges::in_value_result<int, int>&>);37 38struct C {39 C(int&);40};41static_assert(!std::is_constructible_v<std::ranges::in_value_result<C, C>, std::ranges::in_value_result<int, int>&>);42 43// has to be convertible via const&44static_assert(std::is_convertible_v<std::ranges::in_value_result<int, int>&, std::ranges::in_value_result<long, long>>);45static_assert(46 std::is_convertible_v<const std::ranges::in_value_result<int, int>&, std::ranges::in_value_result<long, long>>);47static_assert(48 std::is_convertible_v<std::ranges::in_value_result<int, int>&&, std::ranges::in_value_result<long, long>>);49static_assert(50 std::is_convertible_v<const std::ranges::in_value_result<int, int>&&, std::ranges::in_value_result<long, long>>);51 52// should be move constructible53static_assert(std::is_move_constructible_v<std::ranges::in_value_result<MoveOnly, int>>);54static_assert(std::is_move_constructible_v<std::ranges::in_value_result<int, MoveOnly>>);55 56// should not be copy constructible with move-only type57static_assert(!std::is_copy_constructible_v<std::ranges::in_value_result<MoveOnly, int>>);58static_assert(!std::is_copy_constructible_v<std::ranges::in_value_result<int, MoveOnly>>);59 60struct NotConvertible {};61// conversions should not work if there is no conversion62static_assert(63 !std::is_convertible_v<std::ranges::in_value_result<NotConvertible, int>, std::ranges::in_value_result<int, int>>);64static_assert(65 !std::is_convertible_v<std::ranges::in_value_result<int, NotConvertible>, std::ranges::in_value_result<int, int>>);66 67template <class T>68struct ConvertibleFrom {69 constexpr ConvertibleFrom(T c) : content{c} {}70 T content;71};72 73constexpr bool test() {74 // Checks that conversion operations are correct.75 {76 std::ranges::in_value_result<int, double> res{10, 0.};77 assert(res.in == 10);78 assert(res.value == 0.);79 std::ranges::in_value_result<ConvertibleFrom<int>, ConvertibleFrom<double>> res2 = res;80 assert(res2.in.content == 10);81 assert(res2.value.content == 0.);82 }83 84 // Checks that conversions are possible when one of the types is move-only.85 {86 std::ranges::in_value_result<MoveOnly, int> res{MoveOnly{}, 2};87 assert(res.in.get() == 1);88 assert(res.value == 2);89 auto res2 = static_cast<std::ranges::in_value_result<MoveOnly, int>>(std::move(res));90 assert(res.in.get() == 0);91 assert(res2.in.get() == 1);92 assert(res2.value == 2);93 }94 95 // Checks that structured bindings get the correct values.96 {97 auto [in, value] = std::ranges::in_value_result<int, int>{1, 2};98 assert(in == 1);99 assert(value == 2);100 }101 return true;102}103 104int main(int, char**) {105 test();106 static_assert(test());107 108 return 0;109}110