Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > const and non-const string iterators

Reply
Thread Tools

const and non-const string iterators

 
 
Old Wolf
Guest
Posts: n/a
 
      04-06-2005
Hi all. G++ fails to compile the following:

#include <string>

int main()
{
std::string foo("abc=123");
std::string::const_iterator delimiter
= std::find(foo.begin(), foo.end(), '=');

std::string left (foo.begin(), delimiter);
}

The construction of 'left' fails, saying that there's no matching
constructor. The problem appears to be that it is searching
for a constructor taking (iterator, const_iterator) and finds
none. Is this conforming behaviour?

The following change doesn't fix it:

std::string::const_iterator
begin = foo.begin(),
delimiter = std::find(begin, foo.end(), '=');
std::string left (begin, delimiter);

Now it complains that there's no match for std::find() for
the same reason. The following does compile correctly:

std::string::const_iterator
begin = foo.begin(),
end = foo.end(),
delimiter = std::find(begin, end, '=');
std::string left (begin, delimiter);

I thought that non-const iterators should be implicitly
converted to const ones, or that the version of begin()
that returns a const_iterator should be found when it's
trying to find a matching call to std::find().
BCC has no problem with the code.

 
Reply With Quote
 
 
 
 
Thierry Miceli
Guest
Posts: n/a
 
      04-06-2005

"Old Wolf" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed) oups.com...
> Hi all. G++ fails to compile the following:
>
> #include <string>
>
> int main()
> {
> std::string foo("abc=123");
> std::string::const_iterator delimiter
> = std::find(foo.begin(), foo.end(), '=');
>
> std::string left (foo.begin(), delimiter);
> }
>
> The construction of 'left' fails, saying that there's no matching
> constructor. The problem appears to be that it is searching
> for a constructor taking (iterator, const_iterator) and finds
> none. Is this conforming behaviour?


Yes.
The function template you are trying to instanciate has the following
declaration:

template <class InputIterator >
basic_string(
InputIterator _First,
InputIterator _Last,
const allocator_type& _Al = Allocator ( )
);

You can see that the type of the first and second parameters of the function
template correspond to the same type. The compiler cannot deduce that it is
this constructor that you want to call if your call has a combination of
string::const_iterator and string::iterator as arguments.

>
> The following change doesn't fix it:
>
> std::string::const_iterator
> begin = foo.begin(),
> delimiter = std::find(begin, foo.end(), '=');
> std::string left (begin, delimiter);
>
> Now it complains that there's no match for std::find() for
> the same reason.


Same problem here. The general find function is declared as:

template<class InputIterator, class Type>
InputIterator find(
InputIterator _First,
InputIterator _Last,
const Type& _Val
);

Again _First and _Last must have the same type.


> The following does compile correctly:
>
> std::string::const_iterator
> begin = foo.begin(),
> end = foo.end(),
> delimiter = std::find(begin, end, '=');
> std::string left (begin, delimiter);
>
> I thought that non-const iterators should be implicitly
> converted to const ones, or that the version of begin()
> that returns a const_iterator should be found when it's
> trying to find a matching call to std::find().
> BCC has no problem with the code.
>

There is no type conversion for the instanciation of function templates. A
template type parameter (e.g. InputIterator) is substituted with the same
type (e.g. string::const_iterator) wherever it appears in the template
definition to generate the template instance.


Regards,

Thierry Miceli
www.ideat-solutions.com



 
Reply With Quote
 
 
 
 
George Faraj
Guest
Posts: n/a
 
      04-06-2005
Well, I compiled your code in VC++ 7.1 and it compiled and worked correctly:

#include <iostream>
#include <string>
#include <algorithm>

using namespace std;

int main()
{
string foo = "abc=123";
string::const_iterator delimiter = std::find(foo.begin(), foo.end(),
'=');
string left(foo.begin(), delimiter);

cout << left << endl;
return 0;
}

Is that a recent version of g++ that you tested it on? I guess VC++ 7.1 just
looks harder for constructors

> The following change doesn't fix it:
>
> std::string::const_iterator
> begin = foo.begin(),
> delimiter = std::find(begin, foo.end(), '=');
> std::string left (begin, delimiter);


Well, if you want to use that, change:

> delimiter = std::find(begin, foo.end(), '=');

to:
> delimiter = std::find(foo.begin(), foo.end(), '=');


Hope that helps,
George Faraj



"Old Wolf" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed) oups.com...
> Hi all. G++ fails to compile the following:
>
> #include <string>
>
> int main()
> {
> std::string foo("abc=123");
> std::string::const_iterator delimiter
> = std::find(foo.begin(), foo.end(), '=');
>
> std::string left (foo.begin(), delimiter);
> }
>
> The construction of 'left' fails, saying that there's no matching
> constructor. The problem appears to be that it is searching
> for a constructor taking (iterator, const_iterator) and finds
> none. Is this conforming behaviour?
>
> The following change doesn't fix it:
>
> std::string::const_iterator
> begin = foo.begin(),
> delimiter = std::find(begin, foo.end(), '=');
> std::string left (begin, delimiter);
>
> Now it complains that there's no match for std::find() for
> the same reason. The following does compile correctly:
>
> std::string::const_iterator
> begin = foo.begin(),
> end = foo.end(),
> delimiter = std::find(begin, end, '=');
> std::string left (begin, delimiter);
>
> I thought that non-const iterators should be implicitly
> converted to const ones, or that the version of begin()
> that returns a const_iterator should be found when it's
> trying to find a matching call to std::find().
> BCC has no problem with the code.
>



 
Reply With Quote
 
Thierry Miceli
Guest
Posts: n/a
 
      04-06-2005

"George Faraj" <(E-Mail Removed)> wrote in message
news:d305ud$6jr$(E-Mail Removed)...
> Well, I compiled your code in VC++ 7.1 and it compiled and worked

correctly:
It does not compile with Comeau which is one of the best compilers (if not
the best) at implementing the C++ standard.
I get the following error:

line 12: error: no instance of constructor

This code should not compile since string::iterator and
string::const_iterator are different types.
Anybody as an opinion on this? Is VC++ wrong?


Thierry Miceli
www.ideat-solutions.com


 
Reply With Quote
 
gfaraj gfaraj is offline
Junior Member
Join Date: Oct 2006
Posts: 1
 
      10-16-2006
Hehe, I was searching for my name in google and this topic came out. I forgot to follow-up on it some time ago. I'm going to do that now, if it even matters anymore.

Comeau is right, VC++ is wrong (not that it's a rare occurrence). basic_string's range constructor does not support different iterator types. This appears to be a special case in VC8, which allows the above mentioned code but rejects the following:

Code:
template <typename T>
void f(T, T)
{
}

int main()
{
     f(10, 10L);
}
saying that the template parameter T is ambiguous: could be int or long. This seems very reasonable, though it struck me as strange that it accepted the call to string's range constructor with different iterator types.

I decided to investigate a little more, and realized that VC8's stdlib implementation defines two additional constructors for basic_string. They are:

Code:
basic_string(const_pointer, const_pointer)
basic_string(const_iterator, const_iterator)
These non-standard constructors are the ones allowing the mentioned code compile in VC8. It would probably be wise to consider adding these constructors to the standard, though.

Just to clarify, the code in question is malformed according to the standard. To make it compile, you would explicitly construct a const_iterator:

Code:
string left(string::const_iterator(foo.begin()), delimiter);
Hope that helps whoever still reads this stuff,
George Faraj
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
plain iterators and reverse iterators on vector subramanian100in@yahoo.com, India C++ 10 08-08-2009 08:28 AM
is const necessary in eg int compar(const void *, const void *) lovecreatesbeauty@gmail.c0m C Programming 26 11-10-2008 09:47 PM
const vector<A> vs vector<const A> vs const vector<const A> Javier C++ 2 09-04-2007 08:46 PM
Casting int'** to 'const int * const * const' dosn't work, why? Jonas.Holmsten@gmail.com C Programming 11 07-01-2007 06:16 PM
Iterators and reverse iterators Marcin Kaliciński C++ 1 05-08-2005 09:58 AM



Advertisments