On Tue, 23 Aug 2022, Jonathan Wakely wrote:

> On Tue, 23 Aug 2022 at 02:35, Patrick Palka via Libstdc++
> <libstd...@gcc.gnu.org> wrote:
> >
> > P2321R2 adds new conditionally explicit constructors to std::tuple which
> > we'll concisely implement in a subsequent patch using explicit(bool), like
> > in our C++20 std::pair implementation.  But before we can do that, this
> > patch first adds members to _TupleConstraints that test for constructibility
> > and convertibility separately; we'll use the first in the new constructors'
> > constraints, and the second in their explicit specifier.
> >
> > In passing, this patch also redefines the existing predicates
> > __is_ex/implicitly_constructible in terms of these new members.  This
> > seems to reduce compile time and memory usage by about 10% for large
> 
> Nice.
> 
> > tuples when using the relevant constructors constrained by
> > _Explicit/_ImplicitCtor (since we no longer have to redundantly expand
> > and process is_constructible<_Types, _UTypes>... twice for each pair of
> > such constructors).  In order to retain maximal short circuiting, do
> > this only when constexpr if is available.
> 
> Would we get similar benefits for C++11 and C++14 by doing:
> 
>        return __and_<__and_<is_constructible<_Types, _UTypes>...>,
>                      __and_<is_convertible<_UTypes, _Types>...>
>                      >::value;
> 
> This is slightly more work in total, but if we have __and_<A,B> and
> __and_<A,__not_<B>> then the A and B instantiations will be cached and
> can be reused.

Good idea, it seems we get pretty much the same 10% improvement for
C++11/14 with this approach.  I reckon we might as well then define
__convertible and __constructible as alias templates instead of as
variable templates and use them unconditionally in
__is_im/explicitly_constructible for benefit of all language versions.
Using constexpr if instead of the outer __and_ seems to yield a marginal
improvement at best and __and_v is currently just __and_::value, so it
doesn't seem worth it to have different definitions for C++17 at least
for now.

What do you think about the following?

-- >8 --

libstdc++-v3/ChangeLog:

        * include/std/tuple (_TupleConstraints::__convertible): Define.
        (_TupleConstraints::__constructible): Likewise.
        (_TupleConstraints::__is_explicitly_constructible): Redefine this
        in terms of __convertible and __constructible.
        (_TupleConstraints::__is_implicitly_constructible): Likewise.
---
 libstdc++-v3/include/std/tuple | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple
index 6d0060a191c..f8f48ccc370 100644
--- a/libstdc++-v3/include/std/tuple
+++ b/libstdc++-v3/include/std/tuple
@@ -553,15 +553,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<bool, typename... _Types>
     struct _TupleConstraints
     {
+      template<typename... _UTypes>
+       using __constructible = __and_<is_constructible<_Types, _UTypes>...>;
+
+      template<typename... _UTypes>
+       using __convertible = __and_<is_convertible<_UTypes, _Types>...>;
+
       // Constraint for a non-explicit constructor.
       // True iff each Ti in _Types... can be constructed from Ui in _UTypes...
       // and every Ui is implicitly convertible to Ti.
       template<typename... _UTypes>
        static constexpr bool __is_implicitly_constructible()
        {
-         return __and_<is_constructible<_Types, _UTypes>...,
-                       is_convertible<_UTypes, _Types>...
-                       >::value;
+         return __and_<__constructible<_UTypes...>,
+                       __convertible<_UTypes...>>::value;
        }
 
       // Constraint for a non-explicit constructor.
@@ -570,9 +575,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       template<typename... _UTypes>
        static constexpr bool __is_explicitly_constructible()
        {
-         return __and_<is_constructible<_Types, _UTypes>...,
-                       __not_<__and_<is_convertible<_UTypes, _Types>...>>
-                       >::value;
+         return __and_<__constructible<_UTypes...>,
+                       __not_<__convertible<_UTypes...>>>::value;
        }
 
       static constexpr bool __is_implicitly_default_constructible()
-- 
2.37.2.382.g795ea8776b

Reply via email to