Now tested in C++98 mode, there was indeed a small problem.
I even wonder if I shouldn't have extend the std::copy overload to any
call with deque iterator as the output so that it is transform into an
output to pointer.
Ok to commit ?
François
On 23/05/20 6:37 pm, Jonathan Wakely wrote:
On 22/05/20 22:57 +0200, François Dumont via Libstdc++ wrote:
On 21/05/20 2:17 pm, Jonathan Wakely wrote:
Why is the optimization not done for C++03 mode?
I did it this way because the new std::copy overload rely on
std::copy_n implementation details which is a C++11 algo.
It looks like the uses of 'auto' can be reaplced easily, and
__enable_if_t<> can be replaced with __gnu_cxx::__enable_if<>::__type.
But yes, we can indeed provide those implementation details in
pre-C++11.
This is what I've done in this new version.
Tested under Linux x86_64 in default c++ mode.
I tried to use CXXFLAGS=-std=c++03 but it doesn't seem to work even
if I do see the option in build logs. I remember you adivised a
different approach, can you tell me again ?
See the documentation:
https://gcc.gnu.org/onlinedocs/libstdc++/manual/test.html#test.run.permutations
diff --git a/libstdc++-v3/include/bits/deque.tcc b/libstdc++-v3/include/bits/deque.tcc
index e773f32b256..d7dbe64f3e1 100644
--- a/libstdc++-v3/include/bits/deque.tcc
+++ b/libstdc++-v3/include/bits/deque.tcc
@@ -1065,6 +1065,57 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
return __result;
}
+ template<bool _IsMove, typename _CharT>
+ typename __gnu_cxx::__enable_if<
+ __is_char<_CharT>::__value,
+ _GLIBCXX_STD_C::_Deque_iterator<_CharT, _CharT&, _CharT*> >::__type
+ __copy_move_a2(
+ istreambuf_iterator<_CharT, char_traits<_CharT> > __first,
+ istreambuf_iterator<_CharT, char_traits<_CharT> > __last,
+ _GLIBCXX_STD_C::_Deque_iterator<_CharT, _CharT&, _CharT*> __result)
+ {
+ if (__first == __last)
+ return __result;
+
+ for (;;)
+ {
+ const std::ptrdiff_t __len = __result._M_last - __result._M_cur;
+ const std::ptrdiff_t __nb
+ = std::__copy_n_a(__first, __len, __result._M_cur, false)
+ - __result._M_cur;
+ __result += __nb;
+
+ if (__nb != __len)
+ break;
+ }
+
+ return __result;
+ }
+
+ template<typename _CharT, typename _Size>
+ typename __gnu_cxx::__enable_if<
+ __is_char<_CharT>::__value,
+ _GLIBCXX_STD_C::_Deque_iterator<_CharT, _CharT&, _CharT*> >::__type
+ __copy_n_a(
+ istreambuf_iterator<_CharT, char_traits<_CharT> > __it, _Size __size,
+ _GLIBCXX_STD_C::_Deque_iterator<_CharT, _CharT&, _CharT*> __result,
+ bool __strict)
+ {
+ if (__size == 0)
+ return __result;
+
+ do
+ {
+ const _Size __len
+ = std::min<_Size>(__result._M_last - __result._M_cur, __size);
+ std::__copy_n_a(__it, __len, __result._M_cur, __strict);
+ __result += __len;
+ __size -= __len;
+ }
+ while (__size != 0);
+ return __result;
+ }
+
template<bool _IsMove,
typename _Tp, typename _Ref, typename _Ptr, typename _OI>
_OI
diff --git a/libstdc++-v3/include/bits/stl_algo.h b/libstdc++-v3/include/bits/stl_algo.h
index 932ece55529..70d8232aece 100644
--- a/libstdc++-v3/include/bits/stl_algo.h
+++ b/libstdc++-v3/include/bits/stl_algo.h
@@ -705,31 +705,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return __result;
}
- template<typename _InputIterator, typename _Size, typename _OutputIterator>
- _GLIBCXX20_CONSTEXPR
- _OutputIterator
- __copy_n_a(_InputIterator __first, _Size __n, _OutputIterator __result)
- {
- if (__n > 0)
- {
- while (true)
- {
- *__result = *__first;
- ++__result;
- if (--__n > 0)
- ++__first;
- else
- break;
- }
- }
- return __result;
- }
-
- template<typename _CharT, typename _Size>
- __enable_if_t<__is_char<_CharT>::__value, _CharT*>
- __copy_n_a(istreambuf_iterator<_CharT, char_traits<_CharT>>,
- _Size, _CharT*);
-
template<typename _InputIterator, typename _Size, typename _OutputIterator>
_GLIBCXX20_CONSTEXPR
_OutputIterator
@@ -738,7 +713,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
return std::__niter_wrap(__result,
__copy_n_a(__first, __n,
- std::__niter_base(__result)));
+ std::__niter_base(__result), true));
}
template<typename _RandomAccessIterator, typename _Size,
diff --git a/libstdc++-v3/include/bits/stl_algobase.h b/libstdc++-v3/include/bits/stl_algobase.h
index d577ef0953b..ecc50a10c9d 100644
--- a/libstdc++-v3/include/bits/stl_algobase.h
+++ b/libstdc++-v3/include/bits/stl_algobase.h
@@ -314,6 +314,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_NOEXCEPT_IF(std::is_nothrow_copy_constructible<_Iterator>::value)
{ return __it; }
+ template<typename _Ite, typename _Seq>
+ _Ite
+ __niter_base(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq,
+ std::random_access_iterator_tag>&);
+
// Reverse the __niter_base transformation to get a
// __normal_iterator back again (this assumes that __normal_iterator
// is only used to wrap random access iterators, like pointers).
@@ -466,6 +471,15 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
__copy_move_a2(istreambuf_iterator<_CharT, char_traits<_CharT> >,
istreambuf_iterator<_CharT, char_traits<_CharT> >, _CharT*);
+ template<bool _IsMove, typename _CharT>
+ typename __gnu_cxx::__enable_if<
+ __is_char<_CharT>::__value,
+ _GLIBCXX_STD_C::_Deque_iterator<_CharT, _CharT&, _CharT*> >::__type
+ __copy_move_a2(
+ istreambuf_iterator<_CharT, char_traits<_CharT> >,
+ istreambuf_iterator<_CharT, char_traits<_CharT> >,
+ _GLIBCXX_STD_C::_Deque_iterator<_CharT, _CharT&, _CharT*>);
+
template<bool _IsMove, typename _II, typename _OI>
_GLIBCXX20_CONSTEXPR
inline _OI
@@ -539,6 +553,41 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
const ::__gnu_debug::_Safe_iterator<_IIte, _ISeq, _ICat>&,
const ::__gnu_debug::_Safe_iterator<_OIte, _OSeq, _OCat>&);
+ template<typename _InputIterator, typename _Size, typename _OutputIterator>
+ _GLIBCXX20_CONSTEXPR
+ _OutputIterator
+ __copy_n_a(_InputIterator __first, _Size __n, _OutputIterator __result,
+ bool)
+ {
+ if (__n > 0)
+ {
+ while (true)
+ {
+ *__result = *__first;
+ ++__result;
+ if (--__n > 0)
+ ++__first;
+ else
+ break;
+ }
+ }
+ return __result;
+ }
+
+ template<typename _CharT, typename _Size>
+ typename __gnu_cxx::__enable_if<
+ __is_char<_CharT>::__value, _CharT*>::__type
+ __copy_n_a(istreambuf_iterator<_CharT, char_traits<_CharT> >,
+ _Size, _CharT*, bool);
+
+ template<typename _CharT, typename _Size>
+ typename __gnu_cxx::__enable_if<
+ __is_char<_CharT>::__value,
+ _GLIBCXX_STD_C::_Deque_iterator<_CharT, _CharT&, _CharT*> >::__type
+ __copy_n_a(istreambuf_iterator<_CharT, char_traits<_CharT> >, _Size,
+ _GLIBCXX_STD_C::_Deque_iterator<_CharT, _CharT&, _CharT*>,
+ bool);
+
/**
* @brief Copies the range [first,last) into result.
* @ingroup mutating_algorithms
diff --git a/libstdc++-v3/include/bits/streambuf_iterator.h b/libstdc++-v3/include/bits/streambuf_iterator.h
index d3f1610fc8d..184c82cd5bf 100644
--- a/libstdc++-v3/include/bits/streambuf_iterator.h
+++ b/libstdc++-v3/include/bits/streambuf_iterator.h
@@ -82,11 +82,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__copy_move_a2(istreambuf_iterator<_CharT2>,
istreambuf_iterator<_CharT2>, _CharT2*);
-#if __cplusplus >= 201103L
template<typename _CharT2, typename _Size>
- friend __enable_if_t<__is_char<_CharT2>::__value, _CharT2*>
- __copy_n_a(istreambuf_iterator<_CharT2>, _Size, _CharT2*);
-#endif
+ friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value,
+ _CharT2*>::__type
+ __copy_n_a(istreambuf_iterator<_CharT2>, _Size, _CharT2*, bool);
template<typename _CharT2>
friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value,
@@ -396,10 +395,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return __result;
}
-#if __cplusplus >= 201103L
template<typename _CharT, typename _Size>
- __enable_if_t<__is_char<_CharT>::__value, _CharT*>
- __copy_n_a(istreambuf_iterator<_CharT> __it, _Size __n, _CharT* __result)
+ typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value,
+ _CharT*>::__type
+ __copy_n_a(istreambuf_iterator<_CharT> __it, _Size __n, _CharT* __result,
+ bool __strict __attribute__((__unused__)))
{
if (__n == 0)
return __result;
@@ -409,12 +409,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
._M_iterator(__it));
_CharT* __beg = __result;
__result += __it._M_sbuf->sgetn(__beg, __n);
- __glibcxx_requires_cond(__result - __beg == __n,
+ __glibcxx_requires_cond(!__strict || __result - __beg == __n,
_M_message(__gnu_debug::__msg_inc_istreambuf)
._M_iterator(__it));
return __result;
}
-#endif // C++11
template<typename _CharT>
typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value,
diff --git a/libstdc++-v3/include/debug/safe_iterator.tcc b/libstdc++-v3/include/debug/safe_iterator.tcc
index f90bbf3d125..ca4e2d52d1d 100644
--- a/libstdc++-v3/include/debug/safe_iterator.tcc
+++ b/libstdc++-v3/include/debug/safe_iterator.tcc
@@ -234,6 +234,12 @@ namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+ template<typename _Ite, typename _Seq>
+ _Ite
+ __niter_base(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq,
+ std::random_access_iterator_tag>& __it)
+ { return __it.base(); }
+
template<bool _IsMove,
typename _Ite, typename _Seq, typename _Cat, typename _OI>
_OI
diff --git a/libstdc++-v3/testsuite/25_algorithms/copy/streambuf_iterators/char/4.cc b/libstdc++-v3/testsuite/25_algorithms/copy/streambuf_iterators/char/4.cc
index fe04e9342e7..bc23497ff0e 100644
--- a/libstdc++-v3/testsuite/25_algorithms/copy/streambuf_iterators/char/4.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/copy/streambuf_iterators/char/4.cc
@@ -22,6 +22,7 @@
#include <algorithm>
#include <cstring>
#include <vector>
+#include <deque>
#include <testsuite_hooks.h>
@@ -76,9 +77,34 @@ void test02()
VERIFY( !memcmp(buffer.data(), buffer_ref, 16500) );
}
+void test03()
+{
+ using namespace std;
+
+ typedef istreambuf_iterator<char> in_iterator_type;
+
+ ifstream fbuf_ref("istream_unformatted-1.txt"),
+ fbuf("istream_unformatted-1.txt");
+
+ char buffer_ref[16500];
+ std::deque<char> buffer(16500, 'a');
+
+ fbuf_ref.read(buffer_ref, 16500);
+
+ in_iterator_type beg(fbuf);
+ in_iterator_type end;
+ copy(beg, end, buffer.begin());
+
+ VERIFY( fbuf_ref.good() );
+ VERIFY( fbuf.good() );
+
+ VERIFY( std::equal(buffer.begin(), buffer.end(), buffer_ref) );
+}
+
int main()
{
test01();
test02();
+ test03();
return 0;
}
diff --git a/libstdc++-v3/testsuite/25_algorithms/copy/streambuf_iterators/char/debug/deque_neg.cc b/libstdc++-v3/testsuite/25_algorithms/copy/streambuf_iterators/char/debug/deque_neg.cc
new file mode 100644
index 00000000000..26627e37440
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/copy/streambuf_iterators/char/debug/deque_neg.cc
@@ -0,0 +1,46 @@
+// Copyright (C) 2020 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/>.
+
+// { dg-do run { xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <iterator>
+#include <sstream>
+#include <deque>
+#include <algorithm>
+
+void test01()
+{
+ using namespace std;
+
+ typedef istreambuf_iterator<char> in_iterator_type;
+
+ const char data1[] = "Drei Phantasien nach Friedrich Holderlin";
+ const string str1(data1);
+ istringstream iss1(str1);
+ in_iterator_type beg1(iss1);
+ in_iterator_type end1;
+ deque<char> d(sizeof(data1) - 2, '0');
+
+ copy(beg1, end1, d.begin());
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/copy_n/debug/istreambuf_ite_deque_neg.cc b/libstdc++-v3/testsuite/25_algorithms/copy_n/debug/istreambuf_ite_deque_neg.cc
new file mode 100644
index 00000000000..ede641820b5
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/copy_n/debug/istreambuf_ite_deque_neg.cc
@@ -0,0 +1,50 @@
+// Copyright (C) 2020 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/>.
+
+// { dg-do run { target c++11 xfail *-*-* } }
+// { dg-require-fileio "" }
+// { dg-require-debug-mode "" }
+
+#include <iterator>
+#include <fstream>
+#include <algorithm>
+#include <deque>
+
+void test01()
+{
+ using namespace std;
+
+ typedef istreambuf_iterator<char> in_iterator_type;
+
+ ifstream fbuf_ref("istream_unformatted-1.txt"),
+ fbuf("istream_unformatted-1.txt");
+
+ char buffer_ref[16500];
+ deque<char> dq(17000, 'a');
+
+ fbuf_ref.read(buffer_ref, 16500);
+
+ in_iterator_type beg(fbuf);
+ copy_n(beg, 17000, dq.begin());
+}
+
+int
+main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/copy_n/istreambuf_iterator/2.cc b/libstdc++-v3/testsuite/25_algorithms/copy_n/istreambuf_iterator/2.cc
new file mode 100644
index 00000000000..5e1a0c2b75b
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/copy_n/istreambuf_iterator/2.cc
@@ -0,0 +1,56 @@
+// { dg-do run { target c++11 } }
+// { dg-require-fileio "" }
+
+// Copyright (C) 2020 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/>.
+
+#include <iterator>
+#include <fstream>
+#include <algorithm>
+#include <cstring>
+
+#include <testsuite_hooks.h>
+
+void test01()
+{
+ using namespace std;
+
+ typedef istreambuf_iterator<char> in_iterator_type;
+
+ ifstream fbuf_ref("istream_unformatted-1.txt"),
+ fbuf("istream_unformatted-1.txt");
+
+ char buffer_ref[16500],
+ buffer[16501];
+
+ fbuf_ref.read(buffer_ref, 16500);
+
+ in_iterator_type beg(fbuf);
+ copy_n(beg, 16500, buffer);
+
+ VERIFY( fbuf_ref.good() );
+ VERIFY( fbuf.good() );
+
+ VERIFY( !memcmp(buffer, buffer_ref, 16500) );
+}
+
+int
+main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/copy_n/istreambuf_iterator/deque.cc b/libstdc++-v3/testsuite/25_algorithms/copy_n/istreambuf_iterator/deque.cc
new file mode 100644
index 00000000000..ace73701b90
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/copy_n/istreambuf_iterator/deque.cc
@@ -0,0 +1,56 @@
+// { dg-do run { target c++11 } }
+// { dg-require-fileio "" }
+
+// Copyright (C) 2020 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/>.
+
+#include <iterator>
+#include <fstream>
+#include <algorithm>
+#include <deque>
+
+#include <testsuite_hooks.h>
+
+void test01()
+{
+ using namespace std;
+
+ typedef istreambuf_iterator<char> in_iterator_type;
+
+ ifstream fbuf_ref("istream_unformatted-1.txt"),
+ fbuf("istream_unformatted-1.txt");
+
+ char buffer_ref[16500];
+ deque<char> dq(16500, 'a');
+
+ fbuf_ref.read(buffer_ref, 16500);
+
+ in_iterator_type beg(fbuf);
+ copy_n(beg, 16500, dq.begin());
+
+ VERIFY( fbuf_ref.good() );
+ VERIFY( fbuf.good() );
+
+ VERIFY( equal(dq.begin(), dq.end(), buffer_ref) );
+}
+
+int
+main()
+{
+ test01();
+ return 0;
+}