summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorredi <redi@138bc75d-0d04-0410-961f-82ee72b054a4>2012-11-01 01:30:34 +0000
committerredi <redi@138bc75d-0d04-0410-961f-82ee72b054a4>2012-11-01 01:30:34 +0000
commitad20e16565562dbeed844b6c317e7f980da5e0d0 (patch)
tree3b118d46a9a52efbbf49620f2e9e7899ec8d45d3
parent8ab50d10e9a4dd7d9ce73ff612699c1c8d4f1896 (diff)
downloadgcc-ad20e16565562dbeed844b6c317e7f980da5e0d0.tar.gz
* include/bits/forward_list.h (forward_list::assign): Dispatch to new
functions based on assignability of elements. (forward_list::_M_assign): Add overloaded functions for assigning via assignment or via clearing and insertion. (forward_list::_M_assign_val): Likewise. (forward_list::_M_move_assign(forward_list&&, false_type)): Do not erase elements that are not moved. * include/bits/forward_list.tcc (forward_list::operator=): Call assign() to copy elements. * testsuite/23_containers/forward_list/cons/10.cc: New. * testsuite/23_containers/forward_list/cons/11.cc: New. * testsuite/23_containers/forward_list/cons/12.cc: New. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@193057 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--libstdc++-v3/ChangeLog15
-rw-r--r--libstdc++-v3/include/bits/forward_list.h89
-rw-r--r--libstdc++-v3/include/bits/forward_list.tcc17
-rw-r--r--libstdc++-v3/testsuite/23_containers/forward_list/cons/10.cc58
-rw-r--r--libstdc++-v3/testsuite/23_containers/forward_list/cons/11.cc50
-rw-r--r--libstdc++-v3/testsuite/23_containers/forward_list/cons/12.cc61
6 files changed, 255 insertions, 35 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 444efda6960..611570dadf9 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,18 @@
+2012-11-01 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ * include/bits/forward_list.h (forward_list::assign): Dispatch to new
+ functions based on assignability of elements.
+ (forward_list::_M_assign): Add overloaded functions for assigning
+ via assignment or via clearing and insertion.
+ (forward_list::_M_assign_val): Likewise.
+ (forward_list::_M_move_assign(forward_list&&, false_type)): Do not
+ erase elements that are not moved.
+ * include/bits/forward_list.tcc (forward_list::operator=): Call
+ assign() to copy elements.
+ * testsuite/23_containers/forward_list/cons/10.cc: New.
+ * testsuite/23_containers/forward_list/cons/11.cc: New.
+ * testsuite/23_containers/forward_list/cons/12.cc: New.
+
2012-10-31 Jonathan Yong <jon_y@users.sourceforge.net>
* config/os/mingw32-w64/os_defines.h: Do not define anymore
diff --git a/libstdc++-v3/include/bits/forward_list.h b/libstdc++-v3/include/bits/forward_list.h
index 8d4915d0e4d..b40fe9b4a9f 100644
--- a/libstdc++-v3/include/bits/forward_list.h
+++ b/libstdc++-v3/include/bits/forward_list.h
@@ -589,7 +589,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* in the range [@a __first,@a __last).
*
* Note that the assignment completely changes the %forward_list and
- * that the number of elements of the resulting %forward_list's is the
+ * that the number of elements of the resulting %forward_list is the
* same as the number of elements assigned. Old data is lost.
*/
template<typename _InputIterator,
@@ -597,9 +597,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
void
assign(_InputIterator __first, _InputIterator __last)
{
- clear();
- insert_after(cbefore_begin(), __first, __last);
- }
+ typedef is_assignable<_Tp, decltype(*__first)> __assignable;
+ _M_assign(__first, __last, __assignable());
+ }
/**
* @brief Assigns a given value to a %forward_list.
@@ -613,10 +613,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
*/
void
assign(size_type __n, const _Tp& __val)
- {
- clear();
- insert_after(cbefore_begin(), __n, __val);
- }
+ { _M_assign_n(__n, __val, is_copy_assignable<_Tp>()); }
/**
* @brief Assigns an initializer_list to a %forward_list.
@@ -628,10 +625,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
*/
void
assign(std::initializer_list<_Tp> __il)
- {
- clear();
- insert_after(cbefore_begin(), __il);
- }
+ { assign(__il.begin(), __il.end()); }
/// Get a copy of the memory allocation object.
allocator_type
@@ -1255,13 +1249,70 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
if (__list._M_get_Node_allocator() == this->_M_get_Node_allocator())
_M_move_assign(std::move(__list), std::true_type());
else
- {
- // The rvalue's allocator cannot be moved, or is not equal,
- // so we need to individually move each element.
- this->assign(std::__make_move_if_noexcept_iterator(__list.begin()),
- std::__make_move_if_noexcept_iterator(__list.end()));
- __list.clear();
- }
+ // The rvalue's allocator cannot be moved, or is not equal,
+ // so we need to individually move each element.
+ this->assign(std::__make_move_if_noexcept_iterator(__list.begin()),
+ std::__make_move_if_noexcept_iterator(__list.end()));
+ }
+
+ // Called by assign(_InputIterator, _InputIterator) if _Tp is
+ // CopyAssignable.
+ template<typename _InputIterator>
+ void
+ _M_assign(_InputIterator __first, _InputIterator __last, true_type)
+ {
+ auto __prev = before_begin();
+ auto __curr = begin();
+ auto __end = end();
+ while (__curr != __end && __first != __last)
+ {
+ *__curr = *__first;
+ ++__prev;
+ ++__curr;
+ ++__first;
+ }
+ if (__first != __last)
+ insert_after(__prev, __first, __last);
+ else if (__curr != __end)
+ erase_after(__prev, __end);
+ }
+
+ // Called by assign(_InputIterator, _InputIterator) if _Tp is not
+ // CopyAssignable.
+ template<typename _InputIterator>
+ void
+ _M_assign(_InputIterator __first, _InputIterator __last, false_type)
+ {
+ clear();
+ insert_after(cbefore_begin(), __first, __last);
+ }
+
+ // Called by assign(size_type, const _Tp&) if Tp is CopyAssignable
+ void
+ _M_assign_n(size_type __n, const _Tp& __val, true_type)
+ {
+ auto __prev = before_begin();
+ auto __curr = begin();
+ auto __end = end();
+ while (__curr != __end && __n > 0)
+ {
+ *__curr = __val;
+ ++__prev;
+ ++__curr;
+ --__n;
+ }
+ if (__n > 0)
+ insert_after(__prev, __n, __val);
+ else if (__curr != __end)
+ erase_after(__prev, __end);
+ }
+
+ // Called by assign(size_type, const _Tp&) if Tp is non-CopyAssignable
+ void
+ _M_assign_n(size_type __n, const _Tp& __val, false_type)
+ {
+ clear();
+ insert_after(cbefore_begin(), __n, __val);
}
};
diff --git a/libstdc++-v3/include/bits/forward_list.tcc b/libstdc++-v3/include/bits/forward_list.tcc
index 4f9a7fad4eb..7395b2029ad 100644
--- a/libstdc++-v3/include/bits/forward_list.tcc
+++ b/libstdc++-v3/include/bits/forward_list.tcc
@@ -165,22 +165,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
std::__alloc_on_copy(__this_alloc, __that_alloc);
}
- iterator __prev1 = before_begin();
- iterator __curr1 = begin();
- iterator __last1 = end();
- const_iterator __first2 = __list.cbegin();
- const_iterator __last2 = __list.cend();
- while (__curr1 != __last1 && __first2 != __last2)
- {
- *__curr1 = *__first2;
- ++__prev1;
- ++__curr1;
- ++__first2;
- }
- if (__first2 == __last2)
- erase_after(__prev1, __last1);
- else
- insert_after(__prev1, __first2, __last2);
+ assign(__list.cbegin(), __list.cend());
}
return *this;
}
diff --git a/libstdc++-v3/testsuite/23_containers/forward_list/cons/10.cc b/libstdc++-v3/testsuite/23_containers/forward_list/cons/10.cc
new file mode 100644
index 00000000000..8c64ed4ec32
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/forward_list/cons/10.cc
@@ -0,0 +1,58 @@
+// { dg-options "-std=gnu++11" }
+
+// Copyright (C) 2012 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 Pred 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/>.
+
+// 23.3.4.2 forward_list construction [forwardlist.cons]
+
+#include <forward_list>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+struct Counter
+{
+ Counter() { ++create; }
+ Counter(const Counter&) { ++create; }
+ ~Counter() { ++destroy; }
+
+ static int create;
+ static int destroy;
+};
+
+int Counter::create = 0;
+int Counter::destroy = 0;
+
+void test01()
+{
+ typedef __gnu_test::uneq_allocator<Counter> alloc;
+ typedef std::forward_list<Counter, alloc> list;
+
+ {
+ Counter c;
+
+ list l( list(10, c, alloc(1)), alloc(2) );
+
+ VERIFY( Counter::create == 21 );
+ VERIFY( Counter::destroy == 10 );
+ }
+ VERIFY( Counter::destroy == 21 );
+}
+
+int main()
+{
+ test01();
+}
diff --git a/libstdc++-v3/testsuite/23_containers/forward_list/cons/11.cc b/libstdc++-v3/testsuite/23_containers/forward_list/cons/11.cc
new file mode 100644
index 00000000000..4c99305ffd7
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/forward_list/cons/11.cc
@@ -0,0 +1,50 @@
+// { dg-options "-std=gnu++11" }
+
+// Copyright (C) 2012 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 Pred 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/>.
+
+// 23.3.4.2 forward_list construction [forwardlist.cons]
+
+#include <forward_list>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+bool fail = false;
+
+struct A
+{
+ A() = default;
+ A(const A&) { if (fail) throw fail; }
+};
+
+void test01()
+{
+ typedef std::forward_list<A> list;
+
+ list l(2);
+ A from[2];
+ fail = true;
+ // Check existing elements are assigned to, instead of creating new ones.
+ // This is QoI, not required by the standard.
+ l.assign(from, from+2);
+ l.assign(2, from[0]);
+}
+
+int main()
+{
+ test01();
+}
diff --git a/libstdc++-v3/testsuite/23_containers/forward_list/cons/12.cc b/libstdc++-v3/testsuite/23_containers/forward_list/cons/12.cc
new file mode 100644
index 00000000000..a1fc3c307f4
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/forward_list/cons/12.cc
@@ -0,0 +1,61 @@
+// { dg-do compile }
+// { dg-options "-std=gnu++11" }
+
+// Copyright (C) 2012 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 Pred 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/>.
+
+// 23.3.4.2 forward_list construction [forwardlist.cons]
+
+#include <forward_list>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+bool fail = false;
+
+struct NonCopyAssignable
+{
+ NonCopyAssignable() = default;
+ NonCopyAssignable(const NonCopyAssignable&) = default;
+ NonCopyAssignable(int) { }
+
+ NonCopyAssignable& operator=(const NonCopyAssignable&) = delete;
+ NonCopyAssignable& operator=(int) = delete;
+};
+
+void test01()
+{
+ typedef std::forward_list<NonCopyAssignable> list;
+
+ list l(2);
+ NonCopyAssignable from[2];
+ int from2[2];
+
+ // Assigning non-Assignable elements is QoI, not required by the standard.
+
+ l = l;
+
+ l.assign(from, from+2);
+ l.assign(2, from[0]);
+
+ l.assign(from2, from2+2);
+ l.assign(2, from2[0]);
+}
+
+int main()
+{
+ test01();
+}