namespace __detail
{
- template<copy_constructible _Tp> requires is_object_v<_Tp>
+ template<typename _Tp>
+ concept __boxable = copy_constructible<_Tp> && is_object_v<_Tp>;
+
+ template<__boxable _Tp>
struct __box : std::optional<_Tp>
{
using std::optional<_Tp>::optional;
}
};
+ // For types which are already semiregular, this specialization of the
+ // semiregular wrapper stores the object directly without going through
+ // std::optional. It provides just the subset of the primary template's
+ // API that we currently use.
+ template<__boxable _Tp> requires semiregular<_Tp>
+ struct __box<_Tp>
+ {
+ private:
+ [[no_unique_address]] _Tp _M_value;
+
+ public:
+ __box() = default;
+
+ constexpr explicit
+ __box(const _Tp& __t)
+ noexcept(is_nothrow_copy_constructible_v<_Tp>)
+ : _M_value{__t}
+ { }
+
+ constexpr explicit
+ __box(_Tp&& __t)
+ noexcept(is_nothrow_move_constructible_v<_Tp>)
+ : _M_value{std::move(__t)}
+ { }
+
+ template<typename... _Args>
+ requires constructible_from<_Tp, _Args...>
+ constexpr
+ __box(in_place_t, _Args&&... __args)
+ noexcept(is_nothrow_constructible_v<_Tp, _Args...>)
+ : _M_value{std::forward<_Args>(__args)...}
+ { }
+
+ constexpr bool
+ has_value() const noexcept
+ { return true; };
+
+ constexpr _Tp&
+ operator*() noexcept
+ { return _M_value; }
+
+ constexpr const _Tp&
+ operator*() const noexcept
+ { return _M_value; }
+
+ constexpr _Tp*
+ operator->() noexcept
+ { return &_M_value; }
+
+ constexpr const _Tp*
+ operator->() const noexcept
+ { return &_M_value; }
+ };
} // namespace __detail
/// A view that contains exactly one element.
{ return _M_value.operator->(); }
private:
- __detail::__box<_Tp> _M_value;
+ [[no_unique_address]] __detail::__box<_Tp> _M_value;
};
namespace __detail
};
_Vp _M_base = _Vp();
- __detail::__box<_Pred> _M_pred;
+ [[no_unique_address]] __detail::__box<_Pred> _M_pred;
[[no_unique_address]] __detail::_CachedPosition<_Vp> _M_cached_begin;
public:
};
_Vp _M_base = _Vp();
- __detail::__box<_Fp> _M_fun;
+ [[no_unique_address]] __detail::__box<_Fp> _M_fun;
public:
transform_view() = default;
};
_Vp _M_base = _Vp();
- __detail::__box<_Pred> _M_pred;
+ [[no_unique_address]] __detail::__box<_Pred> _M_pred;
public:
take_while_view() = default;
{
private:
_Vp _M_base = _Vp();
- __detail::__box<_Pred> _M_pred;
+ [[no_unique_address]] __detail::__box<_Pred> _M_pred;
[[no_unique_address]] __detail::_CachedPosition<_Vp> _M_cached_begin;
public:
--- /dev/null
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+#include <ranges>
+
+using std::ranges::__detail::__box;
+
+using T = decltype([] { return 0; });
+static_assert(std::is_empty_v<__box<T>>);
+static_assert(std::is_nothrow_copy_constructible_v<__box<T>>);
+static_assert(std::is_nothrow_move_constructible_v<__box<T>>);
+static_assert(std::is_nothrow_constructible_v<__box<T>, std::in_place_t>);
+static_assert(requires (__box<T> a) {
+ a = a;
+ a = std::move(a);
+ a.operator*();
+ a.operator->();
+ a.has_value();
+});
+
+struct S
+{
+ S();
+ ~S();
+ S(const S&);
+ S(S&&);
+ S& operator=(const S&);
+ S& operator=(S&&);
+};
+static_assert(std::is_empty_v<__box<S>>);
+static_assert(!std::is_nothrow_copy_constructible_v<__box<S>>
+ && std::is_copy_constructible_v<__box<S>>);
+static_assert(!std::is_nothrow_move_constructible_v<__box<S>>
+ && std::is_move_constructible_v<__box<S>>);
+static_assert(!std::is_nothrow_constructible_v<__box<S>, std::in_place_t>
+ && std::is_constructible_v<__box<S>, std::in_place_t>);
+static_assert(requires (__box<S> a) {
+ a = a;
+ a = std::move(a);
+ a.operator*();
+ a.operator->();
+ a.has_value();
+});
+
+using U = decltype([i=0] { return 0; });
+static_assert(!std::is_empty_v<__box<U>>);
+static_assert(std::is_nothrow_copy_constructible_v<__box<U>>);
+static_assert(std::is_nothrow_move_constructible_v<__box<U>>);
+static_assert(!std::is_nothrow_constructible_v<__box<U>, std::in_place_t>);
+static_assert(requires (__box<U> a) {
+ a = a;
+ a = std::move(a);
+ a.operator*();
+ a.operator->();
+ a.has_value();
+});