The library side looks good to me, with two small comments: * removing version.cc file, that duplicates tests * removing copyright notice from second test (to be confirmed by Jonathan). The test covers all cases, that I could think of.
On Fri, Aug 29, 2025 at 12:22 PM Jakub Jelinek <[email protected]> wrote: > On Fri, Aug 29, 2025 at 11:40:10AM +0200, Jason Merrill wrote: > > > --- gcc/cp/semantics.cc.jj 2025-08-28 10:50:43.432763513 +0200 > > > +++ gcc/cp/semantics.cc 2025-08-28 16:52:48.006806831 +0200 > > > @@ -13591,6 +13591,38 @@ trait_expr_value (cp_trait_kind kind, tr > > > case CPTK_IS_FUNCTION: > > > return type_code1 == FUNCTION_TYPE; > > > + case CPTK_IS_IMPLICIT_LIFETIME: > > > > Please factor this into a predicate (e.g. implicit_lifetime_type_p) that > can > > be used elsewhere in the compiler. > > Done. > > > This is an interesting way to approach "has at least one trivial eligible > > constructor"; I would expect a loop over CLASSTYPE_CONSTRUCTORS checking > > eligible_special_memfn_p (which doesn't exist yet) && trivial_fn_p. But > I > > guess your approach should work, too. > > This came from the paper's chapter 2, > template<typename T> > struct is_implicit_lifetime : std::disjunction< > std::is_scalar<T>, > std::is_array<T>, > std::is_aggregate<T>, > std::conjunction< > std::is_trivially_destructible<T>, > std::disjunction< > std::is_trivially_default_constructible<T>, > std::is_trivially_copy_constructible<T>, > std::is_trivially_move_constructible<T>>>> {}; > except that the is_aggregate part is more complex and can't be done purely > on the library side since CWG2605. > > > For the rvalue case you can just use type1, and build_stub_object will > add > > the rvalue reference. > > Done. > > 2025-08-29 Jakub Jelinek <[email protected]> > > gcc/cp/ > * cp-tree.h: Implement C++23 P2674R1 - A trait for implicit > lifetime > types. > (implicit_lifetime_type_p): Declare. > * tree.cc (implicit_lifetime_type_p): New function. > * cp-trait.def (IS_IMPLICIT_LIFETIME): New unary trait. > * semantics.cc (trait_expr_value): Handle > CPTK_IS_IMPLICIT_LIFETIME. > (finish_trait_expr): Likewise. > * constraint.cc (diagnose_trait_expr): Likewise. > gcc/testsuite/ > * g++.dg/ext/is_implicit_lifetime.C: New test. > libstdc++-v3/ > * 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. > > --- gcc/cp/cp-tree.h.jj 2025-08-23 15:00:04.190788945 +0200 > +++ gcc/cp/cp-tree.h 2025-08-29 12:04:55.294023368 +0200 > @@ -8369,6 +8369,7 @@ extern bool std_layout_type_p > (const_t > extern bool trivial_type_p (const_tree); > extern bool trivially_relocatable_type_p (tree); > extern bool replaceable_type_p (tree); > +extern bool implicit_lifetime_type_p (tree); > extern bool trivially_copyable_p (const_tree); > extern bool type_has_unique_obj_representations (const_tree); > extern bool scalarish_type_p (const_tree); > --- gcc/cp/tree.cc.jj 2025-08-23 15:00:04.291787603 +0200 > +++ gcc/cp/tree.cc 2025-08-29 12:08:47.617979696 +0200 > @@ -5070,6 +5070,42 @@ replaceable_type_p (tree t) > return true; > } > > +/* Returns 1 iff type T is an implicit-lifetime type, as defined in > + [basic.types.general] and [class.prop]. */ > + > +bool > +implicit_lifetime_type_p (tree t) > +{ > + if (SCALAR_TYPE_P (t) > + || (TREE_CODE (t) == ARRAY_TYPE > + && !(TYPE_SIZE (t) && integer_zerop (TYPE_SIZE (t)))) > + /* GNU extension. */ > + || TREE_CODE (t) == VECTOR_TYPE) > + return true; > + if (!CLASS_TYPE_P (t)) > + return false; > + t = TYPE_MAIN_VARIANT (t); > + if (CP_AGGREGATE_TYPE_P (t) > + && (!CLASSTYPE_DESTRUCTOR (t) > + || !user_provided_p (CLASSTYPE_DESTRUCTOR (t)))) > + return true; > + if (is_trivially_xible (BIT_NOT_EXPR, t, NULL_TREE)) > + { > + if (is_trivially_xible (INIT_EXPR, t, make_tree_vec (0))) > + return true; > + tree arg = make_tree_vec (1); > + tree ct > + = cp_build_qualified_type (t, (cp_type_quals (t) | > TYPE_QUAL_CONST)); > + TREE_VEC_ELT (arg, 0) = cp_build_reference_type (ct, > /*rval=*/false); > + if (is_trivially_xible (INIT_EXPR, t, arg)) > + return true; > + TREE_VEC_ELT (arg, 0) = t; > + if (is_trivially_xible (INIT_EXPR, t, arg)) > + return true; > + } > + return false; > +} > + > /* Returns 1 iff type T is a POD type, as defined in [basic.types]. */ > > bool > --- gcc/cp/cp-trait.def.jj 2025-08-29 11:14:27.657997703 +0200 > +++ gcc/cp/cp-trait.def 2025-08-29 11:53:46.940123903 +0200 > @@ -76,6 +76,7 @@ DEFTRAIT_EXPR (IS_EMPTY, "__is_empty", 1 > DEFTRAIT_EXPR (IS_ENUM, "__is_enum", 1) > DEFTRAIT_EXPR (IS_FINAL, "__is_final", 1) > DEFTRAIT_EXPR (IS_FUNCTION, "__is_function", 1) > +DEFTRAIT_EXPR (IS_IMPLICIT_LIFETIME, "__builtin_is_implicit_lifetime", 1) > DEFTRAIT_EXPR (IS_INVOCABLE, "__is_invocable", -1) > DEFTRAIT_EXPR (IS_LAYOUT_COMPATIBLE, "__is_layout_compatible", 2) > DEFTRAIT_EXPR (IS_LITERAL_TYPE, "__is_literal_type", 1) > --- gcc/cp/semantics.cc.jj 2025-08-29 11:14:27.687997312 +0200 > +++ gcc/cp/semantics.cc 2025-08-29 12:06:08.162068723 +0200 > @@ -13591,6 +13591,9 @@ trait_expr_value (cp_trait_kind kind, tr > case CPTK_IS_FUNCTION: > return type_code1 == FUNCTION_TYPE; > > + case CPTK_IS_IMPLICIT_LIFETIME: > + return implicit_lifetime_type_p (type1); > + > case CPTK_IS_INVOCABLE: > return !error_operand_p (build_invoke (type1, type2, tf_none)); > > @@ -13910,6 +13913,7 @@ finish_trait_expr (location_t loc, cp_tr > type to know whether an array is an aggregate, so use kind=4 > here. */ > case CPTK_IS_AGGREGATE: > case CPTK_IS_FINAL: > + case CPTK_IS_IMPLICIT_LIFETIME: > if (!check_trait_type (type1, /* kind = */ 4)) > return error_mark_node; > break; > --- gcc/cp/constraint.cc.jj 2025-08-29 11:14:27.645997860 +0200 > +++ gcc/cp/constraint.cc 2025-08-29 11:53:46.943123862 +0200 > @@ -3170,6 +3170,9 @@ diagnose_trait_expr (location_t loc, tre > case CPTK_IS_FUNCTION: > inform (loc, "%qT is not a function", t1); > break; > + case CPTK_IS_IMPLICIT_LIFETIME: > + inform (decl_loc, "%qT is not an implicit lifetime type", t1); > + break; > case CPTK_IS_INVOCABLE: > { > if (!TREE_VEC_LENGTH (t2)) > --- gcc/testsuite/g++.dg/ext/is_implicit_lifetime.C.jj 2025-08-28 > 14:14:33.475719420 +0200 > +++ gcc/testsuite/g++.dg/ext/is_implicit_lifetime.C 2025-08-28 > 20:36:08.805719765 +0200 > @@ -0,0 +1,139 @@ > +// { dg-do compile { target c++11 } } > +// { dg-options "" } > +// { dg-add-options float16 } > +// { dg-add-options float32 } > +// { dg-add-options float64 } > +// { dg-add-options float128 } > + > +struct A { int a, b, c; }; > +class B { static int a; private: static int b; public: int c; }; > +struct C { C () {} int a, b, c; }; > +struct D { explicit D (int) {} int a, b, c; }; > +struct E : public A { int d, e, f; }; > +struct F : public C { using C::C; int d, e, f; }; > +class G { int a, b; }; > +struct H { private: int a, b; }; > +struct I { protected: int a, b; }; > +struct J { int a, b; void foo (); }; > +struct K { int a, b; virtual void foo (); }; > +struct L : virtual public A { int d, e; }; > +struct M : protected A { int d, e; }; > +struct N : private A { int d, e; }; > +struct O { O () = delete; int a, b, c; }; > +struct P { P () = default; int a, b, c; }; > +struct Q { Q (); Q (const Q &); int a, b, c; }; > +struct R { R (); R (const R &); R (R &&) = default; int a, b, c; }; > +struct S { S (); ~S (); int a, b, c; }; > +struct T { T (); ~T () = default; int a, b, c; }; > +struct U { U (); U (const U &) = default; int a, b, c; }; > +struct V { V () = default; V (const V &); int a, b, c; }; > +enum W { W1 }; > +enum class X : int { X1 }; > +struct Y { int g; int foo (int); }; > +struct Z; > +struct AA { Q a; Q b; }; > +struct AB { Q a; Q b; ~AB () = default; }; > +struct AC { Q a; Q b; ~AC () {} }; > +struct AD : public Q {}; > +struct AE : public Q { ~AE () = default; }; > +struct AF : public Q { ~AF () {} }; > + > +#define SA(X) static_assert ((X), #X) > + > +SA (!__builtin_is_implicit_lifetime (void)); > +SA (!__builtin_is_implicit_lifetime (const void)); > +SA (!__builtin_is_implicit_lifetime (volatile void)); > +SA (__builtin_is_implicit_lifetime (char)); > +SA (__builtin_is_implicit_lifetime (signed char)); > +SA (__builtin_is_implicit_lifetime (const unsigned char)); > +SA (__builtin_is_implicit_lifetime (short)); > +SA (__builtin_is_implicit_lifetime (volatile unsigned short)); > +SA (__builtin_is_implicit_lifetime (int)); > +SA (__builtin_is_implicit_lifetime (unsigned int)); > +SA (__builtin_is_implicit_lifetime (const volatile long)); > +SA (__builtin_is_implicit_lifetime (unsigned long)); > +SA (__builtin_is_implicit_lifetime (long long)); > +SA (__builtin_is_implicit_lifetime (unsigned long long)); > +#ifdef __SIZEOF_INT128__ > +SA (__builtin_is_implicit_lifetime (__int128)); > +SA (__builtin_is_implicit_lifetime (unsigned __int128)); > +#endif > +SA (__builtin_is_implicit_lifetime (float)); > +SA (__builtin_is_implicit_lifetime (double)); > +SA (__builtin_is_implicit_lifetime (long double volatile)); > +#ifdef __STDCPP_FLOAT16_T__ > +SA (__builtin_is_implicit_lifetime (_Float16)); > +#endif > +#ifdef __STDCPP_FLOAT32_T__ > +SA (__builtin_is_implicit_lifetime (_Float32)); > +#endif > +#ifdef __STDCPP_FLOAT64_T__ > +SA (__builtin_is_implicit_lifetime (const _Float64)); > +#endif > +#ifdef __STDCPP_FLOAT128_T__ > +SA (__builtin_is_implicit_lifetime (_Float128)); > +#endif > +#ifdef __STDCPP_BFLOAT16_T__ > +SA (__builtin_is_implicit_lifetime (decltype(0.bf16))); > +#endif > +SA (__builtin_is_implicit_lifetime (W)); > +SA (__builtin_is_implicit_lifetime (const volatile X)); > +SA (__builtin_is_implicit_lifetime (int *)); > +SA (__builtin_is_implicit_lifetime (int (*) (int))); > +SA (__builtin_is_implicit_lifetime (int (Y::*))); > +SA (__builtin_is_implicit_lifetime (int (Y::*) (int))); > +SA (!__builtin_is_implicit_lifetime (int &)); > +SA (!__builtin_is_implicit_lifetime (char &&)); > +SA (__builtin_is_implicit_lifetime (int [])); > +SA (!__builtin_is_implicit_lifetime (int [0])); > +SA (__builtin_is_implicit_lifetime (int [1])); > +SA (__builtin_is_implicit_lifetime (const Y [42])); > +SA (!__builtin_is_implicit_lifetime (int ())); > +SA (!__builtin_is_implicit_lifetime (int () &)); > +SA (!__builtin_is_implicit_lifetime (int () const)); > +SA (!__builtin_is_implicit_lifetime (int (&) ())); > +SA (!__builtin_is_implicit_lifetime (Z)); // { dg-error > "invalid use of incomplete type 'struct Z'" } > +SA (__builtin_is_implicit_lifetime (Z [])); > +SA (__builtin_is_implicit_lifetime (Z [5])); > +SA (__builtin_is_implicit_lifetime (A)); > +SA (__builtin_is_implicit_lifetime (B)); > +SA (__builtin_is_implicit_lifetime (C)); > +SA (__builtin_is_implicit_lifetime (D)); > +SA (__builtin_is_implicit_lifetime (E)); > +SA (__builtin_is_implicit_lifetime (F)); > +SA (__builtin_is_implicit_lifetime (G)); > +SA (__builtin_is_implicit_lifetime (H)); > +SA (__builtin_is_implicit_lifetime (I)); > +SA (__builtin_is_implicit_lifetime (J)); > +SA (!__builtin_is_implicit_lifetime (K)); > +SA (!__builtin_is_implicit_lifetime (L)); > +SA (__builtin_is_implicit_lifetime (M)); > +SA (__builtin_is_implicit_lifetime (N)); > +SA (__builtin_is_implicit_lifetime (O)); > +SA (__builtin_is_implicit_lifetime (P)); > +SA (!__builtin_is_implicit_lifetime (Q)); > +SA (__builtin_is_implicit_lifetime (R)); > +SA (!__builtin_is_implicit_lifetime (S)); > +SA (__builtin_is_implicit_lifetime (S [3])); > +SA (__builtin_is_implicit_lifetime (T)); > +SA (__builtin_is_implicit_lifetime (U)); > +SA (__builtin_is_implicit_lifetime (V)); > +SA (__builtin_is_implicit_lifetime (_Complex double)); > +SA (__builtin_is_implicit_lifetime (int [[gnu::vector_size (4 * sizeof > (int))]])); > +SA (__builtin_is_implicit_lifetime (AA)); > +SA (__builtin_is_implicit_lifetime (AB)); > +SA (!__builtin_is_implicit_lifetime (AC)); > +#if __cplusplus >= 201703L > +SA (__builtin_is_implicit_lifetime (AD)); > +SA (__builtin_is_implicit_lifetime (AE)); > +#else > +SA (!__builtin_is_implicit_lifetime (AD)); > +SA (!__builtin_is_implicit_lifetime (AE)); > +#endif > +SA (!__builtin_is_implicit_lifetime (AF)); > + > +void > +foo (int n) > +{ > + SA (__builtin_is_implicit_lifetime (char [n])); > +} > --- libstdc++-v3/include/bits/version.def.jj 2025-08-23 > 15:00:05.175775859 +0200 > +++ libstdc++-v3/include/bits/version.def 2025-08-28 > 17:06:44.190031458 +0200 > @@ -2091,6 +2091,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"; > --- libstdc++-v3/include/bits/version.h.jj 2025-08-23 > 15:00:05.176775846 +0200 > +++ libstdc++-v3/include/bits/version.h 2025-08-28 17:06:49.160883915 +0200 > @@ -2343,4 +2343,14 @@ > #endif /* !defined(__cpp_lib_constexpr_exceptions) && > defined(__glibcxx_want_constexpr_exceptions) */ > #undef __glibcxx_want_constexpr_exceptions > > +#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) && > defined(__glibcxx_want_is_implicit_lifetime) */ > +#undef __glibcxx_want_is_implicit_lifetime > + > #undef __glibcxx_want_all > --- libstdc++-v3/include/std/type_traits.jj 2025-07-16 > 13:10:11.054411335 +0200 > +++ libstdc++-v3/include/std/type_traits 2025-08-28 > 17:36:11.404329402 +0200 > @@ -46,6 +46,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 > @@ -4052,6 +4053,22 @@ template<typename _Ret, typename _Fn, ty > # 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 > --- libstdc++-v3/src/c++23/std.cc.in.jj 2025-08-23 15:00:05.209775407 +0200 > +++ libstdc++-v3/src/c++23/std.cc.in 2025-08-28 17:10:43.784942152 > +0200 > @@ -3216,6 +3216,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> > --- libstdc++-v3/testsuite/20_util/is_implicit_lifetime/version.cc.jj > 2025-08-28 17:16:17.590650275 +0200 > +++ libstdc++-v3/testsuite/20_util/is_implicit_lifetime/version.cc > 2025-08-28 17:17:07.215014852 +0200 > @@ -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 > The same check is already included in valuce.cc, so I would simply remove thsi file. > --- libstdc++-v3/testsuite/20_util/is_implicit_lifetime/value.cc.jj > 2025-08-28 17:16:20.746609864 +0200 > +++ libstdc++-v3/testsuite/20_util/is_implicit_lifetime/value.cc > 2025-08-28 20:33:41.480591119 +0200 > @@ -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/>. > I haven't seen a copyright notice in the recent libstdc++ test files which I believe is done intentionally. > + > +// { 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> ); > > > Jakub > >
