Bug 83328 - string.insert does not return a iterator when using initializer lists
Summary: string.insert does not return a iterator when using initializer lists
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: libstdc++ (show other bugs)
Version: 7.2.0
: P3 normal
Target Milestone: 9.0
Assignee: Jonathan Wakely
URL:
Keywords: rejects-valid
Depends on:
Blocks:
 
Reported: 2017-12-08 15:20 UTC by gcc-bugs
Modified: 2019-02-08 12:30 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2017-12-08 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description gcc-bugs 2017-12-08 15:20:53 UTC
Hello gcc-team!

According to http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4659.pdf [24.3.2.6.4]
or http://en.cppreference.com/w/cpp/string/basic_string/insert [9]

```
iterator insert(const_iterator p, initializer_list<charT> il
```

should return an iterator, but the following code

```
#include <string>

int main() {
  std::string s = " world!";
  auto it = s.insert(s.begin(), {'h', 'e', 'l', 'l', 'o'});

  return 0;
}
```

fails with

```
string.cpp: In function ‘int main()’:
string.cpp:5:8: error: ‘void it’ has incomplete type
   auto it = s.insert(s.begin(), {'h', 'e', 'l', 'l', 'o'});

        ^~
```

This behaviour is since g++-4.9
Comment 1 Marek Polacek 2017-12-08 16:02:52 UTC
Sounds like this could fix it but I haven't even tried to compile it:

--- a/libstdc++-v3/include/bits/basic_string.h
+++ b/libstdc++-v3/include/bits/basic_string.h
@@ -1586,13 +1586,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        *  @brief  Insert an initializer_list of characters.
        *  @param __p  Iterator referencing location in string to insert at.
        *  @param __l  The initializer_list of characters to insert.
+       *  @return  Iterator referencing the first inserted char.
        *  @throw  std::length_error  If new length exceeds @c max_size().
        */
-      void
+      iterator
       insert(iterator __p, initializer_list<_CharT> __l)
       {
    _GLIBCXX_DEBUG_PEDASSERT(__p >= begin() && __p <= end());
-   this->insert(__p - begin(), __l.begin(), __l.size());
+   const size_type __pos = __p - begin();
+   this->insert(__pos, __l.begin(), __l.size());
+   return iterator(this->_M_data() + __pos);
       }
 #endif // C++11
Comment 2 Marek Polacek 2017-12-08 16:06:00 UTC
I guess include/debug/string should be adjusted too.
Comment 3 Jonathan Wakely 2017-12-08 16:53:57 UTC
Fixing it is an ABI change, so it's not that simple.

It should also have a const_iterator parameter, not iterator, and needs to be fixed for both std::string implementations.
Comment 4 Jakub Jelinek 2018-05-02 10:11:36 UTC
GCC 8.1 has been released.
Comment 5 Jonathan Wakely 2018-06-21 22:01:58 UTC
Author: redi
Date: Thu Jun 21 22:01:25 2018
New Revision: 261866

URL: https://gcc.gnu.org/viewcvs?rev=261866&root=gcc&view=rev
Log:
PR libstdc++/83328 add correct basic_string::insert for initializer_list

The SSO basic_string has a non-standard insert(iterator, initializer_list)
overload, from a C++0x draft. This adds the correct overload, while also
preserving the old one so that the old symbol is still exported from the
library.

The COW basic_string doesn't have any of the C++11 changes to the insert
overloads (they all still have non-const iterator parameters and the
ones that should return an iterator still return void). This doesn't
make any change to the COW string.

	PR libstdc++/83328
	* acinclude.m4 (libtool_VERSION): Bump to 6:26:0.
	* config/abi/pre/gnu.ver: Add GLIBCXX_3.4.26 and export new symbol.
	* configure: Regenerate.
	* include/bits/basic_string.h [_GLIBCXX_USE_CXX11_ABI]
	(basic_string::insert(const_iterator, initializer_list<C>)): Add.
	[_GLIBCXX_USE_CXX11_ABI && !_GLIBCXX_DEFINING_STRING_INSTANTIATIONS]
	(basic_string::insert(iterator, initializer_list<C>)): Suppress
	definition.
	* include/debug/string (basic_string::insert(iterator, C)): Change
	first parameter to const_iterator.
	(basic_string::insert(iterator, size_type, C)): Likewise. Change
	return type to iterator.
	(basic_string::insert(iterator, InputIterator, InputIterator)):
	Likewise.
	(basic_string::insert(iterator, initializer_list<C>)): Change first
	parameter to const_iterator and return type to iterator.
	* src/c++11/string-inst.cc: Extend comment.
	* testsuite/21_strings/basic_string/modifiers/insert/char/83328.cc:
	New.
	* testsuite/21_strings/basic_string/modifiers/insert/wchar_t/83328.cc:
	New.
	* testsuite/util/testsuite_abi.cc: Add new symbol version.

Added:
    trunk/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/insert/char/83328.cc
    trunk/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/insert/wchar_t/83328.cc
Modified:
    trunk/libstdc++-v3/ChangeLog
    trunk/libstdc++-v3/acinclude.m4
    trunk/libstdc++-v3/config/abi/pre/gnu.ver
    trunk/libstdc++-v3/configure
    trunk/libstdc++-v3/include/bits/basic_string.h
    trunk/libstdc++-v3/include/debug/string
    trunk/libstdc++-v3/src/c++11/string-inst.cc
    trunk/libstdc++-v3/testsuite/util/testsuite_abi.cc
Comment 6 Jonathan Wakely 2018-06-21 22:02:12 UTC
Fixed on trunk so far. I'm going to backport this fix to the gcc-8-branch too.
Comment 7 Jakub Jelinek 2018-07-26 11:25:37 UTC
GCC 8.2 has been released.
Comment 8 Jonathan Wakely 2019-02-08 12:30:32 UTC
This isn't going to be backported, because of the new symbols. So fixed for GCC 9 only.