public inbox for libstdc++-cvs@sourceware.org
help / color / mirror / Atom feed
From: Jonathan Wakely <redi@gcc.gnu.org>
To: gcc-cvs@gcc.gnu.org, libstdc++-cvs@gcc.gnu.org
Subject: [gcc r12-4448] libstdc++: Make non-propagating-cache fully constexpr [PR101263]
Date: Fri, 15 Oct 2021 17:27:31 +0000 (GMT)	[thread overview]
Message-ID: <20211015172731.CFE54385842E@sourceware.org> (raw)

https://gcc.gnu.org/g:2c564e813c0626802e5bfb066c094933d5e6a774

commit r12-4448-g2c564e813c0626802e5bfb066c094933d5e6a774
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Fri Oct 15 14:49:21 2021 +0100

    libstdc++: Make non-propagating-cache fully constexpr [PR101263]
    
    libstdc++-v3/ChangeLog:
    
            PR libstdc++/101263
            * include/std/ranges (__cached): New wrapper struct.
            (__non_propagating_cache): Use __cached for contained value.
            (__non_propagating_cache::_M_emplace_deref): Add constexpr. Use
            std::construct_at instead of placement new.
            * testsuite/std/ranges/adaptors/join.cc: Check constexpr works.

Diff:
---
 libstdc++-v3/include/std/ranges                    | 42 +++++++++++++++++-----
 libstdc++-v3/testsuite/std/ranges/adaptors/join.cc | 13 +++++++
 2 files changed, 46 insertions(+), 9 deletions(-)

diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
index 07eae0cf94b..b8de400dfbb 100644
--- a/libstdc++-v3/include/std/ranges
+++ b/libstdc++-v3/include/std/ranges
@@ -1159,9 +1159,34 @@ namespace views::__adaptor
 	// (such as join_view::_M_inner).
       };
 
+    template<typename _Tp>
+      struct __cached
+      {
+	struct _Deref_t { };
+	static constexpr _Deref_t __deref{};
+
+	// Initialize _M_t directly from the result of dereferencing __i.
+	// This avoids any unwanted temporary materialization that would
+	// occur if *__i was bound to a reference before initializing _M_t.
+	template<typename _Iter>
+	  constexpr explicit
+	  __cached(_Deref_t, _Iter&& __i)
+	  : _M_t(*__i)
+	  { }
+
+	template<typename... _Args>
+	  constexpr explicit
+	  __cached(_Args&&... __args)
+	  : _M_t(std::forward<_Args>(__args)...)
+	  { }
+
+	_Tp _M_t;
+      };
+
     template<typename _Tp>
       requires is_object_v<_Tp>
-      struct __non_propagating_cache<_Tp> : protected _Optional_base<_Tp>
+      struct __non_propagating_cache<_Tp>
+      : protected _Optional_base<__cached<_Tp>>
       {
 	__non_propagating_cache() = default;
 
@@ -1205,23 +1230,22 @@ namespace views::__adaptor
 
 	constexpr _Tp&
 	operator*() noexcept
-	{ return this->_M_get(); }
+	{ return this->_M_get()._M_t; }
 
 	constexpr const _Tp&
 	operator*() const noexcept
-	{ return this->_M_get(); }
+	{ return this->_M_get()._M_t; }
 
 	template<typename _Iter>
-	  _Tp&
+	  constexpr _Tp&
 	  _M_emplace_deref(const _Iter& __i)
 	  {
 	    this->_M_reset();
-	    // Using _Optional_base::_M_construct to initialize from '*__i'
-	    // would incur an extra move due to the indirection, so we instead
-	    // use placement new directly.
-	    ::new ((void *) std::__addressof(this->_M_payload._M_payload)) _Tp(*__i);
+	    // Use the special constructor of __cached<_Tp> that does *__i.
+	    std::construct_at(std::__addressof(this->_M_payload._M_payload),
+			      std::in_place, __cached<_Tp>::__deref, __i);
 	    this->_M_payload._M_engaged = true;
-	    return this->_M_get();
+	    return **this;
 	  }
       };
 
diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/join.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/join.cc
index 50af3fdf729..1ec42381ad2 100644
--- a/libstdc++-v3/testsuite/std/ranges/adaptors/join.cc
+++ b/libstdc++-v3/testsuite/std/ranges/adaptors/join.cc
@@ -193,6 +193,18 @@ test11()
     ;
 }
 
+void
+test12()
+{
+  // PR libstdc++/101263
+  constexpr auto b = [] {
+    auto r = std::views::iota(0, 5)
+      | std::views::lazy_split(0)
+      | std::views::join;
+    return r.begin() != r.end();
+  }();
+}
+
 int
 main()
 {
@@ -207,4 +219,5 @@ main()
   test09();
   test10();
   test11();
+  test12();
 }


                 reply	other threads:[~2021-10-15 17:27 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=20211015172731.CFE54385842E@sourceware.org \
    --to=redi@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: link
Be 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).