mercredi 21 septembre 2022

Need help understanding why this invalid C++ code compiles successfully

The following code compile correctly for me in some environments (e.g. on compiler explorer with gcc 9.3.0) and complains in others (CentOS 7.9.2009 (Core), gcc 9.3.1).

#include <iostream>
using namespace std;

int main() {
    std::string name="aakash";
    name.erase(name.begin()+2, name.cend());
    return 0;
}

When I get an error, the error is :

test.cpp:6:40: error: no matching function for call to 'std::basic_string<char>::erase(__gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, std::basic_string<char>::const_iterator)'
    6 |  name.erase(name.begin()+2, name.cend());
      |                                        ^
In file included from /opt/rh/devtoolset-9/root/usr/include/c++/9/string:55,
                 from /opt/rh/devtoolset-9/root/usr/include/c++/9/bits/locale_classes.h:40,
                 from /opt/rh/devtoolset-9/root/usr/include/c++/9/bits/ios_base.h:41,
                 from /opt/rh/devtoolset-9/root/usr/include/c++/9/ios:42,
                 from /opt/rh/devtoolset-9/root/usr/include/c++/9/ostream:38,
                 from /opt/rh/devtoolset-9/root/usr/include/c++/9/iostream:39,
                 from test.cpp:1:
/opt/rh/devtoolset-9/root/usr/include/c++/9/bits/basic_string.h:4698:7: note: candidate: 'std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT, _Traits, _Alloc>::erase(std::basic_string<_CharT, _Traits, _Alloc>::size_type, std::basic_string<_CharT, _Traits, _Alloc>::size_type) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>; std::basic_string<_CharT, _Traits, _Alloc>::size_type = long unsigned int]'
 4698 |       erase(size_type __pos = 0, size_type __n = npos)
      |       ^~~~~
/opt/rh/devtoolset-9/root/usr/include/c++/9/bits/basic_string.h:4698:23: note:   no known conversion for argument 1 from '__gnu_cxx::__normal_iterator<char*, std::basic_string<char> >' to 'std::basic_string<char>::size_type' {aka 'long unsigned int'}
 4698 |       erase(size_type __pos = 0, size_type __n = npos)
      |             ~~~~~~~~~~^~~~~~~~~
/opt/rh/devtoolset-9/root/usr/include/c++/9/bits/basic_string.h:4714:7: note: candidate: 'std::basic_string<_CharT, _Traits, _Alloc>::iterator std::basic_string<_CharT, _Traits, _Alloc>::erase(std::basic_string<_CharT, _Traits, _Alloc>::iterator) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>; std::basic_string<_CharT, _Traits, _Alloc>::iterator = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >; typename _Alloc::rebind<_CharT>::other::pointer = char*]'
 4714 |       erase(iterator __position)
      |       ^~~~~
/opt/rh/devtoolset-9/root/usr/include/c++/9/bits/basic_string.h:4714:7: note:   candidate expects 1 argument, 2 provided
/opt/rh/devtoolset-9/root/usr/include/c++/9/bits/basic_string.h:4734:7: note: candidate: 'std::basic_string<_CharT, _Traits, _Alloc>::iterator std::basic_string<_CharT, _Traits, _Alloc>::erase(std::basic_string<_CharT, _Traits, _Alloc>::iterator, std::basic_string<_CharT, _Traits, _Alloc>::iterator) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>; std::basic_string<_CharT, _Traits, _Alloc>::iterator = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >; typename _Alloc::rebind<_CharT>::other::pointer = char*]'
 4734 |       erase(iterator __first, iterator __last);
      |       ^~~~~
/opt/rh/devtoolset-9/root/usr/include/c++/9/bits/basic_string.h:4734:40: note:   no known conversion for argument 2 from '__normal_iterator<const char*,[...]>' to '__normal_iterator<char*,[...]>'
 4734 |       erase(iterator __first, iterator __last);
      |                               ~~~~~~~~~^~~~~~
      |                               ~~~~~~~~~^~~~~~

The error looks reasonable to me because as per C++ documentation, both arguments to std::basic_string::erase should either be of type iterator or const_iterator.

So when it works (e.g. here), what allows it to work ?

Aucun commentaire:

Enregistrer un commentaire