blob: cf2749d1685fd3af803635cb0254268128575f24 [file] [log] [blame]
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-no-concepts
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
// <algorithm>
//
// namespace ranges {
// template<class InputIterator, class OutputIterator>
// struct in_out_result;
// }
#include <algorithm>
#include <cassert>
#include <type_traits>
struct A {
A(int&);
};
static_assert(!std::is_constructible_v<std::ranges::in_out_result<A, A>, std::ranges::in_out_result<int, int>&>);
static_assert(std::is_convertible_v<std::ranges::in_out_result<int, int>&,
std::ranges::in_out_result<long, long>>);
static_assert(!std::is_nothrow_convertible_v<std::ranges::in_out_result<int, int>&,
std::ranges::in_out_result<long, long>>);
static_assert(std::is_convertible_v<const std::ranges::in_out_result<int, int>&,
std::ranges::in_out_result<long, long>>);
static_assert(!std::is_nothrow_convertible_v<const std::ranges::in_out_result<int, int>&,
std::ranges::in_out_result<long, long>>);
static_assert(std::is_convertible_v<std::ranges::in_out_result<int, int>&&,
std::ranges::in_out_result<long, long>>);
static_assert(!std::is_nothrow_convertible_v<std::ranges::in_out_result<int, int>&&,
std::ranges::in_out_result<long, long>>);
static_assert(std::is_convertible_v<const std::ranges::in_out_result<int, int>&&,
std::ranges::in_out_result<long, long>>);
static_assert(!std::is_nothrow_convertible_v<const std::ranges::in_out_result<int, int>&&,
std::ranges::in_out_result<long, long>>);
int main(int, char**) {
// Conversion, fundamental types.
{
std::ranges::in_out_result<int, bool> x = {2, false};
// FIXME(varconst): try a narrowing conversion.
std::ranges::in_out_result<long, char> y = x;
assert(y.in == 2);
assert(y.out == '\0');
}
// Conversion, user-defined types.
{
struct From1 {
int value = 0;
From1(int v) : value(v) {}
};
struct To1 {
int value = 0;
To1(int v) : value(v) {}
To1(const From1& f) : value(f.value) {};
};
struct To2 {
int value = 0;
To2(int v) : value(v) {}
};
struct From2 {
int value = 0;
From2(int v) : value(v) {}
operator To2() const { return To2(value); }
};
std::ranges::in_out_result<From1, From2> x{42, 99};
std::ranges::in_out_result<To1, To2> y = x;
assert(y.in.value == 42);
assert(y.out.value == 99);
}
// Copy-only type.
{
struct CopyOnly {
int value = 0;
CopyOnly() = default;
CopyOnly(int v) : value(v) {}
CopyOnly(const CopyOnly&) = default;
CopyOnly(CopyOnly&&) = delete;
};
std::ranges::in_out_result<CopyOnly, CopyOnly> x;
x.in.value = 42;
x.out.value = 99;
auto y = x;
assert(y.in.value == 42);
assert(y.out.value == 99);
}
// Move-only type.
{
struct MoveOnly {
int value = 0;
MoveOnly(int v) : value(v) {}
MoveOnly(MoveOnly&&) = default;
MoveOnly(const MoveOnly&) = delete;
};
std::ranges::in_out_result<MoveOnly, MoveOnly> x{42, 99};
auto y = std::move(x);
assert(y.in.value == 42);
assert(y.out.value == 99);
}
// Unsuccessful conversion.
{
struct Foo1 {};
struct Foo2 {};
struct Bar1 {};
struct Bar2 {};
static_assert(
!std::is_convertible_v<std::ranges::in_out_result<Foo1, Foo2>, std::ranges::in_out_result<Bar1, Bar2>>);
}
return 0;
}