From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wr1-x435.google.com (mail-wr1-x435.google.com [IPv6:2a00:1450:4864:20::435]) by sourceware.org (Postfix) with ESMTPS id 5E198385742D; Fri, 21 May 2021 06:55:25 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 5E198385742D Received: by mail-wr1-x435.google.com with SMTP id q5so19906619wrs.4; Thu, 20 May 2021 23:55:25 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=+P6rcVOcNOxH4gM3FQMKPi60X35lp+Y7nz5PTOaGgUQ=; b=IXjenNoqVODt3JO9HIBStxy07UCGTQTFPcTmkMvHRJTRNSfYWj8OrP//OQ1sNKRuVr lFC6ZG+uRkcSLULL3GQnkl7jR+O56NDGjrgBNzOi7vyH/31hJk3Eb4NVliejjFEaTXXU OVct/WtzqIaWxDjHwuYY+M+uS0zG0SSDqg4YLmo/BPCIOJfhSbGDEB6cXQh6sflRn4ne cxt2maRpVm/qVEObaVGJARwwNN2QKAB49q78JdrSH5mD/KBoz878lh7km5hXLDuTMkCD HeYvWgDis3efFOWpG3YLpSKjYAeOVB7ganw6/VI19c/PYgTVlzqnmSAzTupe+j4UMsTt VUiQ== X-Gm-Message-State: AOAM533dUwRjujtBpHeRkIER8T8XeXMF/TG+Btv73U5kF3x453Jj4/98 y1Gz1NUaP4/H2s5I5A+rAcLLGd5o4zOBN93MgPU= X-Google-Smtp-Source: ABdhPJxIQ+qAsONCjQoz7Qpk150K7OyD5WfKoPDQ6m2EWap424V5xUeoIIIoDqU52fCbzaK3yN/7d1ToWJD5M6QRfLg= X-Received: by 2002:a5d:68ca:: with SMTP id p10mr8088919wrw.30.1621580124372; Thu, 20 May 2021 23:55:24 -0700 (PDT) MIME-Version: 1.0 References: <5b198dd5-cb89-91a0-9070-13927ac263a4@gmail.com> <524e2eee-a4ee-a05e-087f-6000c8274eff@gmail.com> <21854fd0-ad6b-1eaa-adaa-2074421fc107@gmail.com> <7bd748f6-77bd-fdcc-f925-1700ac9da3de@gmail.com> <50b5f8f5-56a3-57a5-2e03-b23118a1a2c5@gmail.com> In-Reply-To: From: Jonathan Wakely Date: Fri, 21 May 2021 07:55:13 +0100 Message-ID: Subject: Re: [PATCH] Hashtable PR96088 To: =?UTF-8?Q?Fran=C3=A7ois_Dumont?= Cc: Jonathan Wakely , "libstdc++" , gcc-patches X-Spam-Status: No, score=-1.4 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, HTML_MESSAGE, KAM_NUMSUBJECT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=no autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Content-Filtered-By: Mailman/MimeDel 2.1.29 X-BeenThere: libstdc++@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libstdc++ mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 21 May 2021 06:55:27 -0000 On Fri, 21 May 2021, 07:48 Jonathan Wakely, wrote: > > > On Fri, 21 May 2021, 07:31 Fran=C3=A7ois Dumont via Libstdc++, < > libstdc++@gcc.gnu.org> wrote: > >> On 20/05/21 6:44 pm, Jonathan Wakely wrote: >> > On 06/05/21 22:03 +0200, Fran=C3=A7ois Dumont via Libstdc++ wrote: >> >> Hi >> >> >> >> Considering your feedback on backtrace in debug mode is going to >> >> take me some time so here is another one. >> >> >> >> Compared to latest submission I've added a _Hash_arg_t partial >> >> specialization for std::hash<>. It is not strictly necessary for the >> >> moment but when we will eventually remove its nested argument_type it >> >> will be. I also wonder if it is not easier to handle for the >> >> compiler, not sure about that thought. >> > >> > The std::hash specializations in libstdc++ define argument_type, but >> > I'm already working on one that doesn't (forstd::stacktrace). >> > >> > And std::hash can be specialized by users, >> > and is not required to provide argument_type. >> > >> > So it's already not valid to assume that std::hash::argument_type >> > exists. >> >> Yes, I know that the plan is to get rid of argument_type. But as long as >> it is there we can still use it even if I didn't realize that you were >> already in the process of removing it so soon. >> > > I'm adding a new specialization for a C++23 type, and not adding the > nested types. > > > >> >> > >> >> @@ -850,9 +852,56 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >> >> iterator >> >> _M_emplace(const_iterator, false_type __uks, _Args&&... __args); >> >> >> >> + template >> >> + std::pair >> >> + _M_insert_unique(_Kt&&, _Arg&&, const _NodeGenerator&); >> >> + >> >> + // Detect nested argument_type. >> >> + template> >> >> + struct _Hash_arg_t >> >> + { typedef _Kt argument_type; }; >> >> + >> >> + // std::hash >> >> + template >> >> + struct _Hash_arg_t<_Kt, std::hash<_Arg>> >> >> + { typedef _Arg argument_type; }; >> >> + >> >> + // Nested argument_type. >> >> + template >> >> + struct _Hash_arg_t<_Kt, _Ht, >> >> + __void_t> >> >> + { typedef typename _Ht::argument_type argument_type; }; >> >> + >> >> + // Function pointer. >> >> + template >> >> + struct _Hash_arg_t<_Kt, std::size_t(*)(const _Arg&)> >> >> + { typedef _Arg argument_type; }; >> >> + >> >> + template> >> + typename _ArgType >> >> + =3D typename _Hash_arg_t<_Kt, _Hash>::argument_type> >> >> + static typename conditional< >> >> + __is_nothrow_convertible<_Kt, _ArgType>::value, _Kt&&, >> >> key_type>::type >> > >> > Please use __conditional_t<...> here instead of >> > typename conditional<...>::type. >> > >> > The purpose of the _Hash_arg_t type is to determine whether invoking >> > the hash function with _Kt&& can throw, right? >> >> No, the purpose of _Hash_arg_t is to find out what is the argument type >> of the _Hash functor. With this info I can check if invoking that >> functor is going to instantiate a temporary using a throwing operation. > > > Right, that's what I mean. > > >> If so, I create a temporary at _Hashtable code level and move it to its >> final storage place when needed. >> >> The tricky part is that _Hash can accept different argument types, for >> the moment I just do not create a temporary in this case. >> >> > >> > And if it can throw, you force a conversion early, and if it can't, >> > you don't do the conversion. >> > >> > Can't you use __is_nothrow_invocable<_Hash&, _Kt> for that, instead of >> > this fragile approach? >> > >> I think I already try but I'll check. >> >> I fear that __is_nothrow_invocable<_Hash&, _Kt> tells if the chosen >> operator()(const _Arg&) is noexcept qualified. > > > No. > > Not if the conversion >> from _Kt to _Arg is noexcept. >> > > > It does exactly what you need. > And even if it didn't, you could do it yourself with the noexcept operator: noexcept(std::declval<_Hash&>()(std::declval<_Kt>())); This is what the trait uses, and it tells you if invoking Hash with a Kt will throw. If a conversion to the argument type is needed, the compiler will consider whether that can throw. You don't need to know the argument type, you only need to know if the expression can throw, and C++11 provides the tools to check that accurately= .