This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [Patch] SFINAE on is_same first in variant's _Tp&& constructor
- From: Jonathan Wakely <jwakely at redhat dot com>
- To: Tim Shen <timshen at google dot com>
- Cc: libstdc++ <libstdc++ at gcc dot gnu dot org>, gcc-patches <gcc-patches at gcc dot gnu dot org>
- Date: Mon, 22 May 2017 14:21:37 +0100
- Subject: Re: [Patch] SFINAE on is_same first in variant's _Tp&& constructor
- Authentication-results: sourceware.org; auth=none
- Authentication-results: ext-mx06.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com
- Authentication-results: ext-mx06.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=jwakely at redhat dot com
- Dkim-filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 670AD3D94D
- Dmarc-filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 670AD3D94D
- References: <CAG4ZjNkZui6RkKB-cydS+q1=xUcuNS42Uha6w-N7fK7GbEOmSw@mail.gmail.com>
On 19/05/17 22:40 -0700, Tim Shen via libstdc++ wrote:
diff --git a/libstdc++-v3/include/std/variant b/libstdc++-v3/include/std/variant
index 0e04a820d69..b9824a5182c 100644
--- a/libstdc++-v3/include/std/variant
+++ b/libstdc++-v3/include/std/variant
@@ -936,9 +936,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
noexcept((is_nothrow_move_constructible_v<_Types> && ...)) = default;
template<typename _Tp,
+ typename = enable_if_t<!is_same_v<decay_t<_Tp>, variant>>,
typename = enable_if_t<__exactly_once<__accepted_type<_Tp&&>>
- && is_constructible_v<__accepted_type<_Tp&&>, _Tp&&>
- && !is_same_v<decay_t<_Tp>, variant>>>
+ && is_constructible_v<__accepted_type<_Tp&&>, _Tp&&>>>
Does this definitely short-circuit? I seem to recall a similar case
where either Clang or GCC (I think it was Clang) was evaluating the
second default template argument even though the first had produce a
substition failure.
If we need to guarantee it short-circuits then we'd want:
template<typename _Tp,
typename = enable_if_t<__and_<
__not_<is_same<decay_t<_Tp>, variant>>,
__bool_constant<
__exactly_once<__accepted_type<_Tp&&>>
&& is_constructible_v<__accepted_type<_Tp&&>, _Tp&&>>>
i.e. use __and_< is-this-type, everything-else> where
"everything-else" still uses && to avoid making the instantiations too
deep.
Also, this is another place where we could use an __is_samey<T, U>
trait that does is_same<remove_cv_t<remove_reference_t<T>, U>.