public inbox for libstdc++-cvs@sourceware.org help / color / mirror / Atom feed
From: Patrick Palka <ppalka@gcc.gnu.org> To: gcc-cvs@gcc.gnu.org, libstdc++-cvs@gcc.gnu.org Subject: [gcc r13-2379] libstdc++: Fix laziness of __and/or/not_ Date: Fri, 2 Sep 2022 15:20:18 +0000 (GMT) [thread overview] Message-ID: <20220902152018.E8E303858C54@sourceware.org> (raw) https://gcc.gnu.org/g:51c42b38e43b5283b116882529d232719b099bfc commit r13-2379-g51c42b38e43b5283b116882529d232719b099bfc Author: Patrick Palka <ppalka@redhat.com> Date: Fri Sep 2 11:19:51 2022 -0400 libstdc++: Fix laziness of __and/or/not_ r13-2230-g390f94eee1ae69 redefined the internal logical operator traits __and_, __or_ and __not_ as alias templates that directly resolve to true_type or false_type. But it turns out using an alias template here causes the traits to be less lazy than before because we now compute the logical result immediately upon _specialization_ of the trait, and not later upon _completion_ of the specialization. So for example, in using type = __and_<A, __not_<B>>; we now compute the conjunction and thus instantiate A even though we're in a context that doesn't require completion of the __and_. What's worse is that we also compute the inner negation and thus instantiate B (for the same reason), independent of the __and_ and the value of A! Thus the traits are now less lazy and composable than before. Fortunately, the fix is cheap and straightforward: redefine these traits as class templates instead of as alias templates so that computation of the logical result is triggered by completion, not by specialization. libstdc++-v3/ChangeLog: * include/std/type_traits (__or_, __and_, __not_): Redefine as a class template instead of as an alias template. * testsuite/20_util/logical_traits/requirements/short_circuit.cc: Add more tests for conjunction and disjunction. Add corresponding tests for __and_ and __or_. Diff: --- libstdc++-v3/include/std/type_traits | 12 ++++++--- .../logical_traits/requirements/short_circuit.cc | 29 ++++++++++++++++++++++ 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index 8b11f31741b..be9f2955539 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -168,13 +168,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // to either true_type or false_type which allows for a more efficient // implementation that avoids recursive class template instantiation. template<typename... _Bn> - using __or_ = decltype(__detail::__or_fn<_Bn...>(0)); + struct __or_ + : decltype(__detail::__or_fn<_Bn...>(0)) + { }; template<typename... _Bn> - using __and_ = decltype(__detail::__and_fn<_Bn...>(0)); + struct __and_ + : decltype(__detail::__and_fn<_Bn...>(0)) + { }; template<typename _Pp> - using __not_ = __bool_constant<!bool(_Pp::value)>; + struct __not_ + : __bool_constant<!bool(_Pp::value)> + { }; /// @endcond #if __cplusplus >= 201703L diff --git a/libstdc++-v3/testsuite/20_util/logical_traits/requirements/short_circuit.cc b/libstdc++-v3/testsuite/20_util/logical_traits/requirements/short_circuit.cc index 86996b27fa5..ff90f8a47c3 100644 --- a/libstdc++-v3/testsuite/20_util/logical_traits/requirements/short_circuit.cc +++ b/libstdc++-v3/testsuite/20_util/logical_traits/requirements/short_circuit.cc @@ -14,6 +14,10 @@ static_assert(!std::conjunction_v<std::false_type, invalid>); static_assert(!std::conjunction_v<std::false_type, invalid, invalid>); static_assert(!std::conjunction_v<std::true_type, std::false_type, invalid>); static_assert(!std::conjunction_v<std::true_type, std::false_type, invalid, invalid>); +static_assert(!std::conjunction_v<std::false_type, + std::conjunction<invalid>, + std::disjunction<invalid>, + std::negation<invalid>>); // [meta.logical]/8: For a specialization disjunction<B_1, ..., B_n>, if // there is a template type argument B_i for which bool(B_i::value) is true, @@ -24,3 +28,28 @@ static_assert(std::disjunction_v<std::true_type, invalid>); static_assert(std::disjunction_v<std::true_type, invalid, invalid>); static_assert(std::disjunction_v<std::false_type, std::true_type, invalid>); static_assert(std::disjunction_v<std::false_type, std::true_type, invalid, invalid>); +static_assert(std::disjunction_v<std::true_type, + std::conjunction<invalid>, + std::disjunction<invalid>, + std::negation<invalid>>); + +#if __GLIBCXX__ +// Also test the corresponding internal traits __and_, __or_ and __not_. +static_assert(!std::__and_v<std::false_type, invalid>); +static_assert(!std::__and_v<std::false_type, invalid, invalid>); +static_assert(!std::__and_v<std::true_type, std::false_type, invalid>); +static_assert(!std::__and_v<std::true_type, std::false_type, invalid, invalid>); +static_assert(!std::__and_v<std::false_type, + std::__and_<invalid>, + std::__or_<invalid>, + std::__not_<invalid>>); + +static_assert(std::__or_v<std::true_type, invalid>); +static_assert(std::__or_v<std::true_type, invalid, invalid>); +static_assert(std::__or_v<std::false_type, std::true_type, invalid>); +static_assert(std::__or_v<std::false_type, std::true_type, invalid, invalid>); +static_assert(std::__or_v<std::true_type, + std::__and_<invalid>, + std::__or_<invalid>, + std::__not_<invalid>>); +#endif
reply other threads:[~2022-09-02 15:20 UTC|newest] Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20220902152018.E8E303858C54@sourceware.org \ --to=ppalka@gcc.gnu.org \ --cc=gcc-cvs@gcc.gnu.org \ --cc=libstdc++-cvs@gcc.gnu.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).