On Tue, 3 Dec 2024 at 16:56, Jonathan Wakely <jwak...@redhat.com> wrote: > > On Tue, 3 Dec 2024 at 16:19, Giuseppe D'Angelo > <giuseppe.dang...@kdab.com> wrote: > > > > Hello, > > > > The attached patch changes std::weak_ptr "converting move > > constructor/assignment" -- that is, from a rvalue weak_ptr<Derived> to a > > weak_ptr<Base>. > > > > In the general case, such conversion requires lock()ing the weak_ptr > > because the pointed-to object might have already been destroyed, and a > > Derived->Base pointer conversion requires dereferencing the pointer iff > > Base is a virtual base class of Derived. Therefore the correct thing to > > do in the general case is to lock() the weak_ptr, call get() on the > > resulting shared_ptr, and do the pointer conversion while this > > shared_ptr is alive. > > > > However, the newly added __is_virtual_base_of builtin allows us to > > micro-optimize this pointer upcast, and avoid calling lock() (and paying > > for the associated atomic operations) in case Base is *not* a virtual > > base class of Derived. In this case we can "just" perform the upcast; > > as far as I know, no ABI requires dereferencing the pointer in the > > non-virtual inheritance case. > > This is a nice optimization! > > We would usually use _S_safe_upcast for the name of a static member > function, although I think __safe_upcast is OK here. > > Do we need the _Compatible constraint on __safe_upcast? It's only > called internally from code that has already enforced that constraint, > so checking again just slows compilation down. > > I've been moving from using `if _GLIBCXX17_CONSTEXPR` to just > surrounding the function in diagnostic pragmas so that we can use `if > constexpr` unconditionally, i.e. > > #pragma GCC diagnostic push > #pragma GCC diagnostic pushignored "-Wc++17-extensions" // if constexpr > ... > #pragma GCC diagnostic pop > > That way we get the benefits of `if constexpr` even in C++11 mode. > > We still have lots of code using _GLIBCXX17_CONSTEXPR but I think we > should phase it out in favour of using `if constexpr` unconditionally > (or at least using `if _GLIBCXX_CONSTEXPR` for code which needs to > compile as C++98 too).
Ah, I think we also need to guard the use of the built-in with a preprocessor check to ensure it's available. So maybe invert the sense of the condition, so that the fast path is only present when the built-in is supported: #if __has_builtin(__builtin_is_virtual_base_of) if constexpr (!__builtin_is_virtual_base_of(_Tp, _Yp)) return __r._M_ptr; else #endif return __r.lock().get(); We should probably even be using the _GLIBCXX_USE_BUILTIN_TRAIT macro here, so that its use can be disabled.