mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-12-24 11:35:31 +08:00
d319517e80
We already have conditional noexcept so this just constrains the non-member swap overload. Signed-off-by: Jonathan Wakely <jwakely@redhat.com> libstdc++-v3/ChangeLog: * include/experimental/propagate_const (swap): Constrain. * testsuite/experimental/propagate_const/swap/lwg3413.cc: New test.
547 lines
15 KiB
C++
547 lines
15 KiB
C++
// <experimental/propagate_const> -*- C++ -*-
|
|
|
|
// Copyright (C) 2015-2021 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.
|
|
|
|
// Under Section 7 of GPL version 3, you are granted additional
|
|
// permissions described in the GCC Runtime Library Exception, version
|
|
// 3.1, as published by the Free Software Foundation.
|
|
|
|
// You should have received a copy of the GNU General Public License and
|
|
// a copy of the GCC Runtime Library Exception along with this program;
|
|
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
|
// <http://www.gnu.org/licenses/>.
|
|
|
|
/** @file experimental/propagate_const
|
|
* This is a TS C++ Library header.
|
|
* @ingroup libfund-ts
|
|
*/
|
|
|
|
#ifndef _GLIBCXX_EXPERIMENTAL_PROPAGATE_CONST
|
|
#define _GLIBCXX_EXPERIMENTAL_PROPAGATE_CONST 1
|
|
|
|
#pragma GCC system_header
|
|
|
|
#if __cplusplus >= 201402L
|
|
|
|
#include <type_traits>
|
|
#include <bits/functional_hash.h>
|
|
#include <bits/move.h>
|
|
#include <bits/stl_function.h>
|
|
#include <experimental/bits/lfts_config.h>
|
|
|
|
namespace std _GLIBCXX_VISIBILITY(default)
|
|
{
|
|
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|
|
|
namespace experimental
|
|
{
|
|
inline namespace fundamentals_v2
|
|
{
|
|
/**
|
|
* @defgroup propagate_const Const-propagating wrapper
|
|
* @ingroup libfund-ts
|
|
*
|
|
* A const-propagating wrapper that propagates const to pointer-like members,
|
|
* as described in n4388 "A Proposal to Add a Const-Propagating Wrapper
|
|
* to the Standard Library".
|
|
*
|
|
* @{
|
|
*/
|
|
|
|
/// Const-propagating wrapper.
|
|
template <typename _Tp>
|
|
class propagate_const
|
|
{
|
|
public:
|
|
typedef remove_reference_t<decltype(*std::declval<_Tp&>())> element_type;
|
|
|
|
private:
|
|
template <typename _Up>
|
|
struct __is_propagate_const : false_type
|
|
{ };
|
|
|
|
template <typename _Up>
|
|
struct __is_propagate_const<propagate_const<_Up>> : true_type
|
|
{ };
|
|
|
|
template <typename _Up>
|
|
friend constexpr const _Up&
|
|
get_underlying(const propagate_const<_Up>& __pt) noexcept;
|
|
template <typename _Up>
|
|
friend constexpr _Up&
|
|
get_underlying(propagate_const<_Up>& __pt) noexcept;
|
|
|
|
template <typename _Up>
|
|
static constexpr element_type*
|
|
__to_raw_pointer(_Up* __u)
|
|
{ return __u; }
|
|
|
|
template <typename _Up>
|
|
static constexpr element_type*
|
|
__to_raw_pointer(_Up& __u)
|
|
{ return __u.get(); }
|
|
|
|
template <typename _Up>
|
|
static constexpr const element_type*
|
|
__to_raw_pointer(const _Up* __u)
|
|
{ return __u; }
|
|
|
|
template <typename _Up>
|
|
static constexpr const element_type*
|
|
__to_raw_pointer(const _Up& __u)
|
|
{ return __u.get(); }
|
|
|
|
public:
|
|
static_assert(__and_<is_object<typename remove_pointer<_Tp>::type>,
|
|
__not_<is_array<_Tp>>,
|
|
__or_<is_class<_Tp>, is_pointer<_Tp>>>::value,
|
|
"propagate_const requires a class or a pointer to an"
|
|
" object type");
|
|
|
|
// [propagate_const.ctor], constructors
|
|
constexpr propagate_const() = default;
|
|
propagate_const(const propagate_const& __p) = delete;
|
|
constexpr propagate_const(propagate_const&& __p) = default;
|
|
|
|
template <typename _Up, typename
|
|
enable_if<__and_<is_constructible<_Tp, _Up&&>,
|
|
is_convertible<_Up&&, _Tp>>::value, bool
|
|
>::type=true>
|
|
constexpr propagate_const(propagate_const<_Up>&& __pu)
|
|
: _M_t(std::move(get_underlying(__pu)))
|
|
{}
|
|
|
|
template <typename _Up, typename
|
|
enable_if<__and_<is_constructible<_Tp, _Up&&>,
|
|
__not_<is_convertible<_Up&&, _Tp>>>::value,
|
|
bool>::type=false>
|
|
constexpr explicit propagate_const(propagate_const<_Up>&& __pu)
|
|
: _M_t(std::move(get_underlying(__pu)))
|
|
{}
|
|
|
|
template <typename _Up, typename
|
|
enable_if<__and_<is_constructible<_Tp, _Up&&>,
|
|
is_convertible<_Up&&, _Tp>,
|
|
__not_<__is_propagate_const<
|
|
typename decay<_Up>::type>>
|
|
>::value, bool>::type=true>
|
|
constexpr propagate_const(_Up&& __u)
|
|
: _M_t(std::forward<_Up>(__u))
|
|
{}
|
|
|
|
template <typename _Up, typename
|
|
enable_if<__and_<is_constructible<_Tp, _Up&&>,
|
|
__not_<is_convertible<_Up&&, _Tp>>,
|
|
__not_<__is_propagate_const<
|
|
typename decay<_Up>::type>>
|
|
>::value, bool>::type=false>
|
|
constexpr explicit propagate_const(_Up&& __u)
|
|
: _M_t(std::forward<_Up>(__u))
|
|
{}
|
|
|
|
// [propagate_const.assignment], assignment
|
|
propagate_const& operator=(const propagate_const& __p) = delete;
|
|
constexpr propagate_const& operator=(propagate_const&& __p) = default;
|
|
|
|
template <typename _Up, typename =
|
|
typename enable_if<is_convertible<_Up&&, _Tp>::value>::type>
|
|
constexpr propagate_const& operator=(propagate_const<_Up>&& __pu)
|
|
{
|
|
_M_t = std::move(get_underlying(__pu));
|
|
return *this;
|
|
}
|
|
|
|
template <typename _Up, typename =
|
|
typename enable_if<__and_<is_convertible<_Up&&, _Tp>,
|
|
__not_<__is_propagate_const<
|
|
typename decay<_Up>::type>>
|
|
>::value>::type>
|
|
constexpr propagate_const& operator=(_Up&& __u)
|
|
{
|
|
_M_t = std::forward<_Up>(__u);
|
|
return *this;
|
|
}
|
|
|
|
// [propagate_const.const_observers], const observers
|
|
explicit constexpr operator bool() const
|
|
{
|
|
return bool(_M_t);
|
|
}
|
|
|
|
constexpr const element_type* operator->() const
|
|
{
|
|
return get();
|
|
}
|
|
|
|
template <typename _Up = _Tp,
|
|
typename enable_if<__or_<is_pointer<_Up>,
|
|
is_convertible<_Up,
|
|
const element_type*>
|
|
>::value, bool>::type = true>
|
|
constexpr operator const element_type*() const
|
|
{
|
|
return get();
|
|
}
|
|
|
|
constexpr const element_type& operator*() const
|
|
{
|
|
return *get();
|
|
}
|
|
|
|
constexpr const element_type* get() const
|
|
{
|
|
return __to_raw_pointer(_M_t);
|
|
}
|
|
|
|
// [propagate_const.non_const_observers], non-const observers
|
|
constexpr element_type* operator->()
|
|
{
|
|
return get();
|
|
}
|
|
|
|
template <typename _Up = _Tp,
|
|
typename enable_if<__or_<is_pointer<_Up>,
|
|
is_convertible<_Up,
|
|
const element_type*>
|
|
>::value, bool>::type = true>
|
|
constexpr operator element_type*()
|
|
{
|
|
return get();
|
|
}
|
|
|
|
constexpr element_type& operator*()
|
|
{
|
|
return *get();
|
|
}
|
|
|
|
constexpr element_type* get()
|
|
{
|
|
return __to_raw_pointer(_M_t);
|
|
}
|
|
|
|
// [propagate_const.modifiers], modifiers
|
|
constexpr void
|
|
swap(propagate_const& __pt) noexcept(__is_nothrow_swappable<_Tp>::value)
|
|
{
|
|
using std::swap;
|
|
swap(_M_t, get_underlying(__pt));
|
|
}
|
|
|
|
private:
|
|
_Tp _M_t;
|
|
};
|
|
|
|
// [propagate_const.relational], relational operators
|
|
template <typename _Tp>
|
|
constexpr bool
|
|
operator==(const propagate_const<_Tp>& __pt, nullptr_t)
|
|
{
|
|
return get_underlying(__pt) == nullptr;
|
|
}
|
|
|
|
template <typename _Tp>
|
|
constexpr bool
|
|
operator==(nullptr_t, const propagate_const<_Tp>& __pu)
|
|
{
|
|
return nullptr == get_underlying(__pu);
|
|
}
|
|
|
|
template <typename _Tp>
|
|
constexpr bool
|
|
operator!=(const propagate_const<_Tp>& __pt, nullptr_t)
|
|
{
|
|
return get_underlying(__pt) != nullptr;
|
|
}
|
|
|
|
template <typename _Tp>
|
|
constexpr bool operator!=(nullptr_t, const propagate_const<_Tp>& __pu)
|
|
{
|
|
return nullptr != get_underlying(__pu);
|
|
}
|
|
|
|
template <typename _Tp, typename _Up>
|
|
constexpr bool
|
|
operator==(const propagate_const<_Tp>& __pt,
|
|
const propagate_const<_Up>& __pu)
|
|
{
|
|
return get_underlying(__pt) == get_underlying(__pu);
|
|
}
|
|
|
|
template <typename _Tp, typename _Up>
|
|
constexpr bool
|
|
operator!=(const propagate_const<_Tp>& __pt,
|
|
const propagate_const<_Up>& __pu)
|
|
{
|
|
return get_underlying(__pt) != get_underlying(__pu);
|
|
}
|
|
|
|
template <typename _Tp, typename _Up>
|
|
constexpr bool
|
|
operator<(const propagate_const<_Tp>& __pt,
|
|
const propagate_const<_Up>& __pu)
|
|
{
|
|
return get_underlying(__pt) < get_underlying(__pu);
|
|
}
|
|
|
|
template <typename _Tp, typename _Up>
|
|
constexpr bool
|
|
operator>(const propagate_const<_Tp>& __pt,
|
|
const propagate_const<_Up>& __pu)
|
|
{
|
|
return get_underlying(__pt) > get_underlying(__pu);
|
|
}
|
|
|
|
template <typename _Tp, typename _Up>
|
|
constexpr bool
|
|
operator<=(const propagate_const<_Tp>& __pt,
|
|
const propagate_const<_Up>& __pu)
|
|
{
|
|
return get_underlying(__pt) <= get_underlying(__pu);
|
|
}
|
|
|
|
template <typename _Tp, typename _Up>
|
|
constexpr bool
|
|
operator>=(const propagate_const<_Tp>& __pt,
|
|
const propagate_const<_Up>& __pu)
|
|
{
|
|
return get_underlying(__pt) >= get_underlying(__pu);
|
|
}
|
|
|
|
template <typename _Tp, typename _Up>
|
|
constexpr bool
|
|
operator==(const propagate_const<_Tp>& __pt, const _Up& __u)
|
|
{
|
|
return get_underlying(__pt) == __u;
|
|
}
|
|
|
|
template <typename _Tp, typename _Up>
|
|
constexpr bool
|
|
operator!=(const propagate_const<_Tp>& __pt, const _Up& __u)
|
|
{
|
|
return get_underlying(__pt) != __u;
|
|
}
|
|
|
|
template <typename _Tp, typename _Up>
|
|
constexpr bool
|
|
operator<(const propagate_const<_Tp>& __pt, const _Up& __u)
|
|
{
|
|
return get_underlying(__pt) < __u;
|
|
}
|
|
|
|
template <typename _Tp, typename _Up>
|
|
constexpr bool
|
|
operator>(const propagate_const<_Tp>& __pt, const _Up& __u)
|
|
{
|
|
return get_underlying(__pt) > __u;
|
|
}
|
|
|
|
template <typename _Tp, typename _Up>
|
|
constexpr bool
|
|
operator<=(const propagate_const<_Tp>& __pt, const _Up& __u)
|
|
{
|
|
return get_underlying(__pt) <= __u;
|
|
}
|
|
|
|
template <typename _Tp, typename _Up>
|
|
constexpr bool
|
|
operator>=(const propagate_const<_Tp>& __pt, const _Up& __u)
|
|
{
|
|
return get_underlying(__pt) >= __u;
|
|
}
|
|
|
|
template <typename _Tp, typename _Up>
|
|
constexpr bool
|
|
operator==(const _Tp& __t, const propagate_const<_Up>& __pu)
|
|
{
|
|
return __t == get_underlying(__pu);
|
|
}
|
|
|
|
template <typename _Tp, typename _Up>
|
|
constexpr bool
|
|
operator!=(const _Tp& __t, const propagate_const<_Up>& __pu)
|
|
{
|
|
return __t != get_underlying(__pu);
|
|
}
|
|
|
|
template <typename _Tp, typename _Up>
|
|
constexpr bool
|
|
operator<(const _Tp& __t, const propagate_const<_Up>& __pu)
|
|
{
|
|
return __t < get_underlying(__pu);
|
|
}
|
|
|
|
template <typename _Tp, typename _Up>
|
|
constexpr bool
|
|
operator>(const _Tp& __t, const propagate_const<_Up>& __pu)
|
|
{
|
|
return __t > get_underlying(__pu);
|
|
}
|
|
|
|
template <typename _Tp, typename _Up>
|
|
constexpr bool
|
|
operator<=(const _Tp& __t, const propagate_const<_Up>& __pu)
|
|
{
|
|
return __t <= get_underlying(__pu);
|
|
}
|
|
|
|
template <typename _Tp, typename _Up>
|
|
constexpr bool
|
|
operator>=(const _Tp& __t, const propagate_const<_Up>& __pu)
|
|
{
|
|
return __t >= get_underlying(__pu);
|
|
}
|
|
|
|
// [propagate_const.algorithms], specialized algorithms
|
|
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
|
// 3413. propagate_const's swap [...] needs to be constrained and use a trait
|
|
template <typename _Tp>
|
|
constexpr enable_if_t<__is_swappable<_Tp>::value, void>
|
|
swap(propagate_const<_Tp>& __pt, propagate_const<_Tp>& __pt2)
|
|
noexcept(__is_nothrow_swappable<_Tp>::value)
|
|
{
|
|
__pt.swap(__pt2);
|
|
}
|
|
|
|
// [propagate_const.underlying], underlying pointer access
|
|
template <typename _Tp>
|
|
constexpr const _Tp&
|
|
get_underlying(const propagate_const<_Tp>& __pt) noexcept
|
|
{
|
|
return __pt._M_t;
|
|
}
|
|
|
|
template <typename _Tp>
|
|
constexpr _Tp&
|
|
get_underlying(propagate_const<_Tp>& __pt) noexcept
|
|
{
|
|
return __pt._M_t;
|
|
}
|
|
|
|
/// @} group propagate_const
|
|
} // namespace fundamentals_v2
|
|
} // namespace experimental
|
|
|
|
// [propagate_const.hash], hash support
|
|
template <typename _Tp>
|
|
struct hash<experimental::propagate_const<_Tp>>
|
|
{
|
|
using result_type = size_t;
|
|
using argument_type = experimental::propagate_const<_Tp>;
|
|
|
|
size_t
|
|
operator()(const experimental::propagate_const<_Tp>& __t) const
|
|
noexcept(noexcept(hash<_Tp>{}(get_underlying(__t))))
|
|
{
|
|
return hash<_Tp>{}(get_underlying(__t));
|
|
}
|
|
};
|
|
|
|
// [propagate_const.comparison_function_objects], comparison function objects
|
|
template <typename _Tp>
|
|
struct equal_to<experimental::propagate_const<_Tp>>
|
|
{
|
|
constexpr bool
|
|
operator()(const experimental::propagate_const<_Tp>& __x,
|
|
const experimental::propagate_const<_Tp>& __y) const
|
|
{
|
|
return equal_to<_Tp>{}(get_underlying(__x), get_underlying(__y));
|
|
}
|
|
|
|
typedef experimental::propagate_const<_Tp> first_argument_type;
|
|
typedef experimental::propagate_const<_Tp> second_argument_type;
|
|
typedef bool result_type;
|
|
};
|
|
|
|
template <typename _Tp>
|
|
struct not_equal_to<experimental::propagate_const<_Tp>>
|
|
{
|
|
constexpr bool
|
|
operator()(const experimental::propagate_const<_Tp>& __x,
|
|
const experimental::propagate_const<_Tp>& __y) const
|
|
{
|
|
return not_equal_to<_Tp>{}(get_underlying(__x), get_underlying(__y));
|
|
}
|
|
|
|
typedef experimental::propagate_const<_Tp> first_argument_type;
|
|
typedef experimental::propagate_const<_Tp> second_argument_type;
|
|
typedef bool result_type;
|
|
};
|
|
|
|
template <typename _Tp>
|
|
struct less<experimental::propagate_const<_Tp>>
|
|
{
|
|
constexpr bool
|
|
operator()(const experimental::propagate_const<_Tp>& __x,
|
|
const experimental::propagate_const<_Tp>& __y) const
|
|
{
|
|
return less<_Tp>{}(get_underlying(__x), get_underlying(__y));
|
|
}
|
|
|
|
typedef experimental::propagate_const<_Tp> first_argument_type;
|
|
typedef experimental::propagate_const<_Tp> second_argument_type;
|
|
typedef bool result_type;
|
|
};
|
|
|
|
template <typename _Tp>
|
|
struct greater<experimental::propagate_const<_Tp>>
|
|
{
|
|
constexpr bool
|
|
operator()(const experimental::propagate_const<_Tp>& __x,
|
|
const experimental::propagate_const<_Tp>& __y) const
|
|
{
|
|
return greater<_Tp>{}(get_underlying(__x), get_underlying(__y));
|
|
}
|
|
|
|
typedef experimental::propagate_const<_Tp> first_argument_type;
|
|
typedef experimental::propagate_const<_Tp> second_argument_type;
|
|
typedef bool result_type;
|
|
};
|
|
|
|
template <typename _Tp>
|
|
struct less_equal<experimental::propagate_const<_Tp>>
|
|
{
|
|
constexpr bool
|
|
operator()(const experimental::propagate_const<_Tp>& __x,
|
|
const experimental::propagate_const<_Tp>& __y) const
|
|
{
|
|
return less_equal<_Tp>{}(get_underlying(__x), get_underlying(__y));
|
|
}
|
|
|
|
typedef experimental::propagate_const<_Tp> first_argument_type;
|
|
typedef experimental::propagate_const<_Tp> second_argument_type;
|
|
typedef bool result_type;
|
|
};
|
|
|
|
template <typename _Tp>
|
|
struct greater_equal<experimental::propagate_const<_Tp>>
|
|
{
|
|
constexpr bool
|
|
operator()(const experimental::propagate_const<_Tp>& __x,
|
|
const experimental::propagate_const<_Tp>& __y) const
|
|
{
|
|
return greater_equal<_Tp>{}(get_underlying(__x), get_underlying(__y));
|
|
}
|
|
|
|
typedef experimental::propagate_const<_Tp> first_argument_type;
|
|
typedef experimental::propagate_const<_Tp> second_argument_type;
|
|
typedef bool result_type;
|
|
};
|
|
|
|
_GLIBCXX_END_NAMESPACE_VERSION
|
|
} // namespace std
|
|
|
|
#endif // C++14
|
|
|
|
#endif // _GLIBCXX_EXPERIMENTAL_PROPAGATE_CONST
|