On Tue, 23 Sept 2025 at 08:15, Tomasz Kaminski <[email protected]> wrote: > > 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.
Indeed: https://gcc.gnu.org/onlinedocs/libstdc++/manual/test.html#test.new_tests It's not _wrong_ to add it as long as you really are contributing it under a copyright assignment to FSF (which is true for Jakub) but it's not required for most tests. They're not legally significant if all they're doing is poking at an API to check it behaves correctly, and they don't implement any interesting "business logic" or do anything useful. >> >> + >> +// { 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 >>
