The example program below will exhibit the problem when compiled with -std=c++0x or gnu++0x flag. The problem is particularly unfortunate, as rope is designed for use with back_inserter style constructs. Example program: #include <iostream> #include <ext/rope> using namespace std; int main(int argc, char **argv) { __gnu_cxx::crope line("test"); auto ii(back_inserter(line)); *ii++ = 'm'; *ii++ = 'e'; cout << line << endl; return 0; } Compilation error message: testrope1.cpp: In function ‘int main(int, char**)’: testrope1.cpp:11: error: ambiguous overload for ‘operator=’ in ‘ii.std::back_insert_iterator<_Container>::operator++ [with _Container = __gnu_cxx::rope<char, std::allocator<char> >](0).std::back_insert_iterator<_Container>::operator* [with _Container = __gnu_cxx::rope<char, std::allocator<char> >]() = 'm'’ /usr/lib/gcc/x86_64-pc-linux-gnu/4.4.2/include/g++-v4/bits/stl_iterator.h:415: note: candidates are: std::back_insert_iterator<_Container>& std::back_insert_iterator<_Container>::operator=(typename _Container::const_reference) [with _Container = __gnu_cxx::rope<char, std::allocator<char> >] /usr/lib/gcc/x86_64-pc-linux-gnu/4.4.2/include/g++-v4/bits/stl_iterator.h:423: note: std::back_insert_iterator<_Container>& std::back_insert_iterator<_Container>::operator=(typename _Container::value_type&&) [with _Container = __gnu_cxx::rope<char, std::allocator<char> >] testrope1.cpp:12: error: ambiguous overload for ‘operator=’ in ‘ii.std::back_insert_iterator<_Container>::operator++ [with _Container = __gnu_cxx::rope<char, std::allocator<char> >](0).std::back_insert_iterator<_Container>::operator* [with _Container = __gnu_cxx::rope<char, std::allocator<char> >]() = 'e'’ /usr/lib/gcc/x86_64-pc-linux-gnu/4.4.2/include/g++-v4/bits/stl_iterator.h:415: note: candidates are: std::back_insert_iterator<_Container>& std::back_insert_iterator<_Container>::operator=(typename _Container::const_reference) [with _Container = __gnu_cxx::rope<char, std::allocator<char> >] /usr/lib/gcc/x86_64-pc-linux-gnu/4.4.2/include/g++-v4/bits/stl_iterator.h:423: note: std::back_insert_iterator<_Container>& std::back_insert_iterator<_Container>::operator=(typename _Container::value_type&&) [with _Container = __gnu_cxx::rope<char, std::allocator<char> >]
confirmed, the ambiguity comes because crope::const_reference is a typedef for char, not const char& template <class _CharT, class _Alloc> class rope : public _Rope_base<_CharT, _Alloc> { public: typedef _CharT value_type; typedef ptrdiff_t difference_type; typedef size_t size_type; typedef _CharT const_reference;
Bah, I'm afraid this is going to be a wontfix. Certainly the back_insert_iterator assignment operators are fine per se in C++0x mode, and I don't think we really want to, eg, add specializations of back_insert_iterator & co for rope...
Wait a minute, however, what about vector<bool>? We can ignore the super-legacy rope, but is the vector<bool> version of the problem known to LWG?
It is, LWG 1334. I'll try to figure in Rapperswil if there is enough consensus about the resolution to warrant an early implementation even if the issue isn't really resolved.
Why is rope super-legacy? It had not enough attention to it, true, but it's a very convenient class in certain cases. Does the bug resolution means that no more changes/updates are expected for gcc supplied rope, so external implementation should be preferred? And if such is the case, shouldn't rope class be marked as deprecated, so that similar functionality class can be proposed for addition elsewhere, in boost, for instance?
what resolution? this bug has no resolution, it's been suspended until we know what the C++ committee decide to do about DR 1334. The proposed resolution to DR 1334 would solve the problem with rope.
Yes, it's considered super-legacy vs hash_map, for example, which is just legacy. The criterion is very simple: we are missing active maintainers. Just for your information, I'm the one who voted for keeping it in the past, because several times other library maintainers were tempted to simply remove it completely from v3 for that reason. It will slowly rot, will not include new ideas which are being included in all the other containers, will not be tested in less common targets, the performance will deteriorate (because, for example, if nobody really knows the details of the implementation, the bits having to do will concurrency will just use slow locks even when not strictly necessary). Thus, if you, or somebody else you are in contact with, really like it, please consider investing time to study its internals and help maintaining it. That said, this specific issue is just an example of LWG 1334, which is about proxy iterators much more generally.
Instead of waiting for the resolution of DR 1334, I'm going to resolve this by adding in C++0x mode the overload: operator=(const typename _Container::value_type&) which is where 1334 is actually going. In any case should be safe from the ODR / compatibility points of view and will allow more testing of C++0x mode.
Subject: Bug 44963 Author: paolo Date: Sun Aug 8 14:54:51 2010 New Revision: 163001 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=163001 Log: 2010-08-08 Paolo Carlini <paolo.carlini@oracle.com> PR libstdc++/44963 * include/bits/stl_iterator.h (insert_iterator<>:: operator=(const typename _Container::value_type&, back_insert_iterator<>:: operator=(const typename _Container::value_type&), front_insert_iterator<>:: operator=(const typename _Container::value_type&))): Add in C++0x mode. * testsuite/ext/rope/44963.cc: New. * testsuite/20_util/weak_ptr/comparison/cmp_neg.cc: Adjust dg-error line number. Added: trunk/libstdc++-v3/testsuite/ext/rope/44963.cc Modified: trunk/libstdc++-v3/ChangeLog trunk/libstdc++-v3/include/bits/stl_iterator.h trunk/libstdc++-v3/testsuite/20_util/weak_ptr/comparison/cmp_neg.cc
Subject: Bug 44963 Author: paolo Date: Sun Aug 8 14:56:10 2010 New Revision: 163002 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=163002 Log: 2010-08-08 Paolo Carlini <paolo.carlini@oracle.com> PR libstdc++/44963 * include/bits/stl_iterator.h (insert_iterator<>:: operator=(const typename _Container::value_type&, back_insert_iterator<>:: operator=(const typename _Container::value_type&), front_insert_iterator<>:: operator=(const typename _Container::value_type&))): Add in C++0x mode. * testsuite/ext/rope/44963.cc: New. Added: branches/gcc-4_5-branch/libstdc++-v3/testsuite/ext/rope/44963.cc Modified: branches/gcc-4_5-branch/libstdc++-v3/ChangeLog branches/gcc-4_5-branch/libstdc++-v3/include/bits/stl_iterator.h
Fixed for 4.5.2.
(In reply to comment #11) > Fixed for 4.5.2. > Thanks. I've been looking into rope data structure per your advice, and indeed, it needs a lot of fixes. It can probably use canned smart pointers and vstrings for added simplicity and it doesn't seem fully thread safe to me in its current form. Hopefully, I'll have some time soon to give a try at reimplementing it.
Any help with it would be appreciated, thanks. In general, if you mean to contribute it's a good idea to sort out first the Copyright Assignment paperwork, which is actually very simple but takes time: http://gcc.gnu.org/contribute.html Thus get the forms from assignments@. Then, it would be nice if before larger rewrites we could figure out more localized improvements to rope.
I also ran into this problem with std::back_insert_iterator of vector<bool> on gcc-4.4.4's libstdc++ (in C++0x mode). Any chance of a 4.4.5 backport, or is the 4.5.x target final?
From now on I will not apply *any* patch not fixing extremely serious regressions to the 4.4.x branch.
(In reply to comment #15) > From now on I will not apply *any* patch not fixing extremely serious > regressions to the 4.4.x branch. Is 'rejects-valid' serious enough? (This compiles with earlier versions.)
No.