libstd++: Implement C++23 P2674R1 - A trait for implicit lifetime types

The following patch attempts to implement the library side of the
C++23 P2674R1 paper.  As mentioned in the paper, since CWG2605
the trait isn't really implementable purely on the library side.

The compiler side has been committed earlier, so this just uses
the new builtin trait on the library side.

2025-10-30  Jakub Jelinek  <jakub@redhat.com>

	* include/bits/version.def (is_implicit_lifetime): New.
	* include/bits/version.h: Regenerate.
	* include/std/type_traits (std::is_implicit_lifetime,
	std::is_implicit_lifetime_v): New trait.
	* src/c++23/std.cc.in (std::is_implicit_lifetime,
	std::is_implicit_lifetime_v): Export.
	* testsuite/20_util/is_implicit_lifetime/version.cc: New test.
	* testsuite/20_util/is_implicit_lifetime/value.cc: New test.
This commit is contained in:
Jakub Jelinek 2025-10-30 08:43:18 +01:00 committed by Jakub Jelinek
parent bd9f3590a3
commit acdf675933
6 changed files with 196 additions and 0 deletions

View File

@ -2191,6 +2191,15 @@ ftms = {
};
};
ftms = {
name = is_implicit_lifetime;
values = {
v = 202302;
cxxmin = 23;
extra_cond = "__has_builtin(__builtin_is_implicit_lifetime)";
};
};
// Standard test specifications.
stds[97] = ">= 199711L";
stds[03] = ">= 199711L";

View File

@ -2455,4 +2455,14 @@
#endif /* !defined(__cpp_lib_philox_engine) */
#undef __glibcxx_want_philox_engine
#if !defined(__cpp_lib_is_implicit_lifetime)
# if (__cplusplus >= 202100L) && (__has_builtin(__builtin_is_implicit_lifetime))
# define __glibcxx_is_implicit_lifetime 202302L
# if defined(__glibcxx_want_all) || defined(__glibcxx_want_is_implicit_lifetime)
# define __cpp_lib_is_implicit_lifetime 202302L
# endif
# endif
#endif /* !defined(__cpp_lib_is_implicit_lifetime) */
#undef __glibcxx_want_is_implicit_lifetime
#undef __glibcxx_want_all

View File

@ -47,6 +47,7 @@
#define __glibcxx_want_is_aggregate
#define __glibcxx_want_is_constant_evaluated
#define __glibcxx_want_is_final
#define __glibcxx_want_is_implicit_lifetime
#define __glibcxx_want_is_invocable
#define __glibcxx_want_is_layout_compatible
#define __glibcxx_want_is_nothrow_convertible
@ -4053,6 +4054,22 @@ template<typename _Ret, typename _Fn, typename... _Args>
# endif
#endif
#ifdef __cpp_lib_is_implicit_lifetime // C++ >= 23
/// True if the type is an implicit-lifetime type.
/// @since C++23
template<typename _Tp>
struct is_implicit_lifetime
: bool_constant<__builtin_is_implicit_lifetime(_Tp)>
{ };
/// @ingroup variable_templates
/// @since C++23
template<typename _Tp>
inline constexpr bool is_implicit_lifetime_v
= __builtin_is_implicit_lifetime(_Tp);
#endif
#ifdef __cpp_lib_reference_from_temporary // C++ >= 23 && ref_{converts,constructs}_from_temp
/// True if _Tp is a reference type, a _Up value can be bound to _Tp in
/// direct-initialization, and a temporary object would be bound to

View File

@ -3230,6 +3230,10 @@ export namespace std
using std::is_scoped_enum;
using std::is_scoped_enum_v;
#endif
#if __cpp_lib_is_implicit_lifetime
using std::is_implicit_lifetime;
using std::is_implicit_lifetime_v;
#endif
}
// <typeindex>

View File

@ -0,0 +1,129 @@
// Copyright (C) 2025 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-do compile { target c++23 } }
// { dg-add-options no_pch }
#include <type_traits>
#ifndef __cpp_lib_is_implicit_lifetime
# error "Feature test macro for is_implicit_lifetime is missing in <type_traits>"
#elif __cpp_lib_is_implicit_lifetime < 202302L
# error "Feature test macro for is_implicit_lifetime has wrong value in <type_traits>"
#endif
#include <testsuite_tr1.h>
template<typename T>
concept Is_implicit_lifetime
= __gnu_test::test_category<std::is_implicit_lifetime, T>(true);
static_assert( ! Is_implicit_lifetime<void> );
static_assert( ! Is_implicit_lifetime<const void> );
static_assert( ! Is_implicit_lifetime<volatile void> );
static_assert( Is_implicit_lifetime<char> );
static_assert( Is_implicit_lifetime<signed char> );
static_assert( Is_implicit_lifetime<const unsigned char> );
static_assert( Is_implicit_lifetime<short> );
static_assert( Is_implicit_lifetime<volatile unsigned short> );
static_assert( Is_implicit_lifetime<int> );
static_assert( Is_implicit_lifetime<unsigned int> );
static_assert( Is_implicit_lifetime<const volatile long> );
static_assert( Is_implicit_lifetime<unsigned long> );
static_assert( Is_implicit_lifetime<long long> );
static_assert( Is_implicit_lifetime<unsigned long long> );
static_assert( Is_implicit_lifetime<float> );
static_assert( Is_implicit_lifetime<double> );
static_assert( Is_implicit_lifetime<long double volatile> );
enum W { W1 };
static_assert( Is_implicit_lifetime<W> );
enum class X : int { X1 };
static_assert( Is_implicit_lifetime<const volatile X> );
static_assert( Is_implicit_lifetime<int *> );
static_assert( Is_implicit_lifetime<int (*) (int)> );
struct Y { int g; int foo (int); };
static_assert( Is_implicit_lifetime<int (Y::*)> );
static_assert( Is_implicit_lifetime<int (Y::*) (int)> );
static_assert( ! Is_implicit_lifetime<int &> );
static_assert( ! Is_implicit_lifetime<char &&> );
static_assert( Is_implicit_lifetime<int []> );
static_assert( Is_implicit_lifetime<int [1]> );
static_assert( Is_implicit_lifetime<const Y [42]> );
static_assert( ! Is_implicit_lifetime<int ()> );
static_assert( ! Is_implicit_lifetime<int () &> );
static_assert( ! Is_implicit_lifetime<int () const> );
static_assert( ! Is_implicit_lifetime<int (&) ()> );
struct Z;
static_assert( Is_implicit_lifetime<Z []> );
static_assert( Is_implicit_lifetime<Z [5]> );
struct A { int a, b, c; };
static_assert( Is_implicit_lifetime<A> );
class B { static int a; private: static int b; public: int c; };
static_assert( Is_implicit_lifetime<B> );
struct C { C () {} int a, b, c; };
static_assert( Is_implicit_lifetime<C> );
struct D { explicit D (int) {} int a, b, c; };
static_assert( Is_implicit_lifetime<D> );
struct E : public A { int d, e, f; };
static_assert( Is_implicit_lifetime<E> );
struct F : public C { using C::C; int d, e, f; };
static_assert( Is_implicit_lifetime<F> );
class G { int a, b; };
static_assert( Is_implicit_lifetime<G> );
struct H { private: int a, b; };
static_assert( Is_implicit_lifetime<H> );
struct I { protected: int a, b; };
static_assert( Is_implicit_lifetime<I> );
struct J { int a, b; void foo (); };
static_assert( Is_implicit_lifetime<J> );
struct K { int a, b; virtual void foo (); };
static_assert( ! Is_implicit_lifetime<K> );
struct L : virtual public A { int d, e; };
static_assert( ! Is_implicit_lifetime<L> );
struct M : protected A { int d, e; };
static_assert( Is_implicit_lifetime<M> );
struct N : private A { int d, e; };
static_assert( Is_implicit_lifetime<N> );
struct O { O () = delete; int a, b, c; };
static_assert( Is_implicit_lifetime<O> );
struct P { P () = default; int a, b, c; };
static_assert( Is_implicit_lifetime<P> );
struct Q { Q (); Q (const Q &); int a, b, c; };
static_assert( ! Is_implicit_lifetime<Q> );
struct R { R (); R (const R &); R (R &&) = default; int a, b, c; };
static_assert( Is_implicit_lifetime<R> );
struct S { S (); ~S (); int a, b, c; };
static_assert( ! Is_implicit_lifetime<S> );
static_assert( Is_implicit_lifetime<S [3]> );
struct T { T (); ~T () = default; int a, b, c; };
static_assert( Is_implicit_lifetime<T> );
struct U { U (); U (const U &) = default; int a, b, c; };
static_assert( Is_implicit_lifetime<U> );
struct V { V () = default; V (const V &); int a, b, c; };
static_assert( Is_implicit_lifetime<V> );
struct AA { Q a; Q b; };
static_assert( Is_implicit_lifetime<AA> );
struct AB { Q a; Q b; ~AB () = default; };
static_assert( Is_implicit_lifetime<AB> );
struct AC { Q a; Q b; ~AC () {} };
static_assert( ! Is_implicit_lifetime<AC> );
struct AD : public Q {};
static_assert( Is_implicit_lifetime<AD> );
struct AE : public Q { ~AE () = default; };
static_assert( Is_implicit_lifetime<AE> );
struct AF : public Q { ~AF () {} };
static_assert( ! Is_implicit_lifetime<AF> );

View File

@ -0,0 +1,27 @@
// Copyright (C) 2025 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-do compile { target c++23 } }
// { dg-add-options no_pch }
#include <version>
#ifndef __cpp_lib_is_implicit_lifetime
# error "Feature test macro for is_implicit_lifetime is missing in <version>"
#elif __cpp_lib_is_implicit_lifetime < 202302L
# error "Feature test macro for is_implicit_lifetime has wrong value in <version>"
#endif