Patchwork implement std::exchange

login
register
mail settings
Submitter Jonathan Wakely
Date May 18, 2013, 4:22 p.m.
Message ID <CAH6eHdTcYOAh9kw7ACCoyQ7HY6jLEUnunBwdvq1pDztSjVC9nQ@mail.gmail.com>
Download mbox | patch
Permalink /patch/244764/
State New
Headers show

Comments

Jonathan Wakely - May 18, 2013, 4:22 p.m.
* include/std/utility (exchange): Define.
        * testsuite/20_util/exchange/1.cc: New.

Tested x86_64-linux, committed to trunk.
commit f368932e633134e5fb50a1e7d6ffcf6aa4b79b0d
Author: Jonathan Wakely <jwakely.gcc@gmail.com>
Date:   Sat May 18 16:27:13 2013 +0100

    	* include/std/utility (exchange): Define.
    	* testsuite/20_util/exchange/1.cc: New.

Patch

diff --git a/libstdc++-v3/include/std/utility b/libstdc++-v3/include/std/utility
index 8142ea4..ee8c6b1 100644
--- a/libstdc++-v3/include/std/utility
+++ b/libstdc++-v3/include/std/utility
@@ -152,6 +152,18 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     get(const std::pair<_Tp1, _Tp2>& __in) noexcept
     { return __pair_get<_Int>::__const_get(__in); }
 
+#if __cplusplus > 201103L
+  /// Assign @p __new_val to @p __obj and return its previous value.
+  template <class _Tp, class _Up = _Tp>
+    inline _Tp
+    exchange(_Tp& __obj, _Up&& __new_val)
+    {
+      _Tp __old_val = std::move(__obj);
+      __obj = std::forward<_Up>(__new_val);
+      return __old_val;
+    }
+#endif
+
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
 
diff --git a/libstdc++-v3/testsuite/20_util/exchange/1.cc b/libstdc++-v3/testsuite/20_util/exchange/1.cc
new file mode 100644
index 0000000..d16d9e9
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/exchange/1.cc
@@ -0,0 +1,103 @@ 
+// { dg-options "-std=gnu++1y" }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// 20.2.3 exchange [utility.exchange]
+
+#include <utility>
+#include <type_traits>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+  const unsigned val = 4;
+  int i = 1;
+  auto prev = std::exchange(i, val);
+  static_assert( std::is_same<decltype(prev), int>::value, "return type" );
+  VERIFY( i == 4 );
+  VERIFY( prev == 1 );
+  prev = std::exchange(i, 3);
+  VERIFY( i == 3 );
+  VERIFY( prev == 4 );
+}
+
+// Default construction from empty braces
+void
+test02()
+{
+  bool test __attribute__((unused)) = true;
+
+  struct DefaultConstructible
+  {
+    DefaultConstructible(int i = 0) : value(i) { }
+    int value;
+  };
+
+  DefaultConstructible x = 1;
+  auto old = std::exchange(x, {});
+  VERIFY( x.value == 0 );
+  VERIFY( old.value == 1 );
+}
+
+// Deduce type of overloaded function
+void
+test03()
+{
+  bool test __attribute__((unused)) = true;
+
+  int (*fp)(int);
+  int f(int);
+  double f(double);
+  std::exchange(fp, &f);
+  VERIFY( fp != nullptr );
+}
+
+void test04()
+{
+  struct From { };
+  struct To {
+    int value = 0;
+    To() = default;
+    To(const To&) = default;
+    To(const From&) = delete;
+    To& operator=(const From&) { value = 1; }
+    To& operator=(From&&) { value = 2; }
+  };
+
+  To t;
+  From f;
+
+  auto prev = std::exchange(t, f);
+  VERIFY( t.value == 1 );
+  VERIFY( prev.value == 0 );
+
+  prev = std::exchange(t, From{});
+  VERIFY( t.value == 2 );
+  VERIFY( prev.value == 1 );
+}
+
+int
+main()
+{
+  test01();
+  test02();
+  test03();
+  test04();
+  return 0;
+}