libstdc++: Define std::is_pointer_interconvertible_base_of for C++20
Implement these traits using the new built-ins that Jakub added recently. Signed-off-by: Jonathan Wakely <jwakely@redhat.com> libstdc++-v3/ChangeLog: * include/std/type_traits (__cpp_lib_is_pointer_interconvertible) (is_pointer_interconvertible_base_of_v) (is_pointer_interconvertible_base_of): Define for C++20. * include/std/version (__cpp_lib_is_pointer_interconvertible): Define. * testsuite/23_containers/span/layout_compat.cc: Use correct feature test macro for std::is_layout_compatible_v. * testsuite/20_util/is_pointer_interconvertible/value.cc: New test. * testsuite/20_util/is_pointer_interconvertible/version.cc: New test.
This commit is contained in:
parent
04ddd108d1
commit
4fa6c0ec35
5 changed files with 93 additions and 1 deletions
|
@ -3389,6 +3389,33 @@ template<typename _Ret, typename _Fn, typename... _Args>
|
|||
inline constexpr bool is_unbounded_array_v
|
||||
= is_unbounded_array<_Tp>::value;
|
||||
|
||||
#if __has_builtin(__is_pointer_interconvertible_base_of)
|
||||
/// True if `_Derived` is standard-layout and has a base class of type `_Base`
|
||||
/// @since C++20
|
||||
template<typename _Base, typename _Derived>
|
||||
struct is_pointer_interconvertible_base_of
|
||||
: bool_constant<__is_pointer_interconvertible_base_of(_Base, _Derived)>
|
||||
{ };
|
||||
|
||||
/// @ingroup variable_templates
|
||||
/// @since C++20
|
||||
template<typename _Base, typename _Derived>
|
||||
constexpr bool is_pointer_interconvertible_base_of_v
|
||||
= __is_pointer_interconvertible_base_of(_Base, _Derived);
|
||||
|
||||
#if __has_builtin(__builtin_is_pointer_interconvertible_with_class)
|
||||
#define __cpp_lib_is_pointer_interconvertible 201907L
|
||||
|
||||
/// True if `__mp` points to the first member of a standard-layout type
|
||||
/// @returns true if `s.*__mp` is pointer-interconvertible with `s`
|
||||
/// @since C++20
|
||||
template<typename _Tp, typename _Mem>
|
||||
constexpr bool
|
||||
is_pointer_interconvertible_with_class(_Mem _Tp::*__mp) noexcept
|
||||
{ return __builtin_is_pointer_interconvertible_with_class(__mp); }
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if __cplusplus > 202002L
|
||||
#define __cpp_lib_is_scoped_enum 202011L
|
||||
|
||||
|
|
|
@ -236,6 +236,10 @@
|
|||
#ifdef _GLIBCXX_HAS_GTHREADS
|
||||
# define __cpp_lib_jthread 201911L
|
||||
#endif
|
||||
#if __has_builtin(__is_pointer_interconvertible_base_of) \
|
||||
&& __has_builtin(__builtin_is_pointer_interconvertible_with_class)
|
||||
# define __cpp_lib_is_pointer_interconvertible 201907L
|
||||
#endif
|
||||
#if __cpp_lib_atomic_wait
|
||||
# define __cpp_lib_latch 201907L
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
// { dg-options "-std=gnu++20" }
|
||||
// { dg-do compile { target c++20 } }
|
||||
#include <type_traits>
|
||||
|
||||
#ifndef __cpp_lib_is_pointer_interconvertible
|
||||
# error "Feature test macro for is_pointer_interconvertible is missing in <type_traits>"
|
||||
#elif __cpp_lib_is_pointer_interconvertible < 201907L
|
||||
# error "Feature test macro for is_pointer_interconvertible has wrong value in <type_traits>"
|
||||
#endif
|
||||
|
||||
static_assert( std::is_pointer_interconvertible_base_of<void, void>::value
|
||||
== std::is_pointer_interconvertible_base_of_v<void, void> );
|
||||
|
||||
struct B { };
|
||||
|
||||
static_assert( std::is_pointer_interconvertible_base_of<B, B>::value
|
||||
== std::is_pointer_interconvertible_base_of_v<B, B> );
|
||||
|
||||
static_assert( std::is_pointer_interconvertible_base_of_v<B, B> );
|
||||
static_assert( std::is_pointer_interconvertible_base_of_v<B, const B> );
|
||||
static_assert( std::is_pointer_interconvertible_base_of_v<const B, B> );
|
||||
static_assert( std::is_pointer_interconvertible_base_of_v<const B, const B> );
|
||||
|
||||
struct D : B { int i; };
|
||||
|
||||
static_assert( std::is_pointer_interconvertible_base_of_v<D, D> );
|
||||
|
||||
static_assert( std::is_pointer_interconvertible_base_of_v<B, D> );
|
||||
static_assert( std::is_pointer_interconvertible_base_of_v<const B, D> );
|
||||
static_assert( std::is_pointer_interconvertible_base_of_v<B, const D> );
|
||||
static_assert( std::is_pointer_interconvertible_base_of_v<const B, const D> );
|
||||
|
||||
static_assert( ! std::is_pointer_interconvertible_base_of_v<D, B> );
|
||||
|
||||
struct E : D { };
|
||||
// E is not standard-layout
|
||||
static_assert( ! std::is_pointer_interconvertible_base_of_v<E, B> );
|
||||
|
||||
struct D1 : B { };
|
||||
struct D2 : B { };
|
||||
struct D3 : D1, D2 { };
|
||||
// B is ambiguously derived
|
||||
static_assert( ! std::is_pointer_interconvertible_base_of_v<B, D3> );
|
||||
|
||||
union U;
|
||||
static_assert( ! std::is_pointer_interconvertible_base_of_v<U, U> );
|
||||
static_assert( ! std::is_pointer_interconvertible_base_of_v<U, D> );
|
||||
|
||||
struct I; // incomplete
|
||||
static_assert( std::is_pointer_interconvertible_base_of_v<I, I> );
|
||||
static_assert( std::is_pointer_interconvertible_base_of_v<I, const I> );
|
|
@ -0,0 +1,10 @@
|
|||
// { dg-options "-std=gnu++20" }
|
||||
// { dg-do compile { target c++20 } }
|
||||
|
||||
#include <version>
|
||||
|
||||
#ifndef __cpp_lib_is_pointer_interconvertible
|
||||
# error "Feature test macro for is_pointer_interconvertible is missing in <version>"
|
||||
#elif __cpp_lib_is_pointer_interconvertible < 201907L
|
||||
# error "Feature test macro for is_pointer_interconvertible has wrong value in <version>"
|
||||
#endif
|
|
@ -27,7 +27,7 @@
|
|||
struct iovec { void* iov_base; std::size_t iov_len; };
|
||||
#endif
|
||||
|
||||
#if __cpp_lib_is_pointer_interconvertible
|
||||
#if __cpp_lib_is_layout_compatible
|
||||
using std::is_layout_compatible_v;
|
||||
#else
|
||||
// A poor substitute for is_layout_compatible_v
|
||||
|
|
Loading…
Add table
Reference in a new issue