Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > value_type of a back_insert_iterator

Reply
Thread Tools

value_type of a back_insert_iterator

 
 
Chyi Pin Lim
Guest
Posts: n/a
 
      12-05-2003
Why is the type for back_insert_iterator void and not the type of its
encapsulating container?

Why:

namespace std {

template<class Category, class T, class Distance = ptrdiff_t,
class Pointer = T*, class Reference = T&> struct
iterator;

template <class Container>
class back_insert_iterator :
public iterator<output_iterator_tag,void,void,void,void> {
protected:
Container* container;
// -- removed for clarity
};
}

Instead of:

template <class Container>
class back_insert_iterator :
public iterator<output_iterator_tag, typename
Container::value_type,void,void,void> {
protected:
Container* container;
// -- removed for clarity
};
 
Reply With Quote
 
 
 
 
P.J. Plauger
Guest
Posts: n/a
 
      12-05-2003
"Chyi Pin Lim" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed) om...

> Why is the type for back_insert_iterator void and not the type of its
> encapsulating container?


Because it's an output iterator, which is a pure sink. (You can't
peek at any of the things stored in the sequence it controls.)

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com


 
Reply With Quote
 
 
 
 
Chyi Pin Lim
Guest
Posts: n/a
 
      12-06-2003
"P.J. Plauger" <(E-Mail Removed)> wrote in message news:<kA8Ab.354$(E-Mail Removed)>...
> "Chyi Pin Lim" <(E-Mail Removed)> wrote in message
> news:(E-Mail Removed) om...
>
> > Why is the type for back_insert_iterator void and not the type of its
> > encapsulating container?

>
> Because it's an output iterator, which is a pure sink. (You can't
> peek at any of the things stored in the sequence it controls.)
>
> P.J. Plauger
> Dinkumware, Ltd.
> http://www.dinkumware.com


True that I can't peek, but in inserting a value, wouldn't it be
beneficial to know the type in case someone wants to use parameterized
constructor / enforce parameterized contruction.

What I meant is as follows:

// following std::copy
template <typename InIt, typename OutIt>
OutIt copy_to_container(InIt begin, InIt end, OutIt result)
{
// want to use value_type for output
*result = OutIt::value_type(begin, end);
return ++result;
}

Using append:

char s[] = "abc";
vector<string> vs(1); // contain 1 string
vector<vector<char> > vvc(1);

copy_to_container(s, s+1, vs.begin()); // ok
copy_to_container(s, s+1, vvc.begin()); // ok
copy_to_container(s, s+2, back_inserter(vs)); // fail to compile


If the value_type of back_inserter is defined as the type of its
encapsulating container, we can utilize that property.

Since this is not possible, please advise on alternative
implementation that is as flexible.
 
Reply With Quote
 
P.J. Plauger
Guest
Posts: n/a
 
      12-06-2003
"Chyi Pin Lim" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed) om...

> "P.J. Plauger" <(E-Mail Removed)> wrote in message

news:<kA8Ab.354$(E-Mail Removed)>...
> > "Chyi Pin Lim" <(E-Mail Removed)> wrote in message
> > news:(E-Mail Removed) om...
> >
> > > Why is the type for back_insert_iterator void and not the type of its
> > > encapsulating container?

> >
> > Because it's an output iterator, which is a pure sink. (You can't
> > peek at any of the things stored in the sequence it controls.)
> >
> > P.J. Plauger
> > Dinkumware, Ltd.
> > http://www.dinkumware.com

>
> True that I can't peek, but in inserting a value, wouldn't it be
> beneficial to know the type in case someone wants to use parameterized
> constructor / enforce parameterized contruction.


It might be, but that's not a requirement for output iterators.

> What I meant is as follows:
>
> // following std::copy
> template <typename InIt, typename OutIt>
> OutIt copy_to_container(InIt begin, InIt end, OutIt result)
> {
> // want to use value_type for output
> *result = OutIt::value_type(begin, end);


Shouldn't there be a loop in here somewhere?

> return ++result;
> }
>
> Using append:
>
> char s[] = "abc";
> vector<string> vs(1); // contain 1 string
> vector<vector<char> > vvc(1);
>
> copy_to_container(s, s+1, vs.begin()); // ok
> copy_to_container(s, s+1, vvc.begin()); // ok
> copy_to_container(s, s+2, back_inserter(vs)); // fail to compile
>
>
> If the value_type of back_inserter is defined as the type of its
> encapsulating container, we can utilize that property.
>
> Since this is not possible, please advise on alternative
> implementation that is as flexible.


If you want to use additional type information to constrain
assignments to an output iterator, you'll have to supply it
by a different channel.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com


 
Reply With Quote
 
ppLiu_china
Guest
Posts: n/a
 
      12-06-2003
"P.J. Plauger" <(E-Mail Removed)> wrote in message news:<kA8Ab.354$(E-Mail Removed)>...
> "Chyi Pin Lim" <(E-Mail Removed)> wrote in message
> news:(E-Mail Removed) om...
>
> > Why is the type for back_insert_iterator void and not the type of its
> > encapsulating container?

>
> Because it's an output iterator, which is a pure sink. (You can't
> peek at any of the things stored in the sequence it controls.)
>
> P.J. Plauger
> Dinkumware, Ltd.
> http://www.dinkumware.com

I agree with P.J.Plauger
 
Reply With Quote
 
ppLiu_china
Guest
Posts: n/a
 
      12-07-2003
http://www.velocityreviews.com/forums/(E-Mail Removed) (ppLiu_china) wrote in message news:<(E-Mail Removed). com>...
> "P.J. Plauger" <(E-Mail Removed)> wrote in message news:<kA8Ab.354$(E-Mail Removed)>...
> > "Chyi Pin Lim" <(E-Mail Removed)> wrote in message
> > news:(E-Mail Removed) om...
> >
> > > Why is the type for back_insert_iterator void and not the type of its
> > > encapsulating container?

> >
> > Because it's an output iterator, which is a pure sink. (You can't
> > peek at any of the things stored in the sequence it controls.)
> >
> > P.J. Plauger
> > Dinkumware, Ltd.
> > http://www.dinkumware.com

> I agree with P.J.Plauger


What I thought is:
if an output iterator exposes its value_type to the user,then someone
who use it like this:
template<typename OutIte>
void f(OutIte ite){
OutIte::value_type value=*ite; //should it be compiled??
...
}
will expect that such a function can be compiled,which exactly can't
be(you can't get the value that refered to by an output iterator).
Now consider what really happened here:
users thought that 'operator *' returns a value of 'value_type',so if
the 'value_type' was some concrete class or primitive type,the
function template above should be compiled according to the semantic
it has.

of course you can let 'operator *' returns a no-meaning value of a
no-meaning type,such as a proxy,or *this(as the ostream_iterator
actually did),but note that what the value_type is,it isn't the return
type of 'operator *',
So it's inconsistent!!!!

But by declaring the value_type as 'void',it can avoid this kind of
inconsistent----because *ite returns 'void',so you actually can't
cache it anywhere.In other ways,the 'void' value_type implies that you
actually coudn't get the value_type,and you shouldn't care about it
either.With that being the case,you can write "*ite=value".
What really important is semantic.

The situation that you present may rarely happen,I think.
If it happened,like P.J.Plauger said,you'll have to supply it
by a different channel.
 
Reply With Quote
 
Chyi Pin Lim
Guest
Posts: n/a
 
      12-08-2003
"P.J. Plauger" <(E-Mail Removed)> wrote in message news:<VKhAb.1919$%(E-Mail Removed)>...
> "Chyi Pin Lim" <(E-Mail Removed)> wrote in message
> news:(E-Mail Removed) om...
>
> > "P.J. Plauger" <(E-Mail Removed)> wrote in message

> news:<kA8Ab.354$(E-Mail Removed)>...
> > > "Chyi Pin Lim" <(E-Mail Removed)> wrote in message
> > > news:(E-Mail Removed) om...
> > >
> > > > Why is the type for back_insert_iterator void and not the type of its
> > > > encapsulating container?
> > >
> > > Because it's an output iterator, which is a pure sink. (You can't
> > > peek at any of the things stored in the sequence it controls.)
> > >
> > > P.J. Plauger
> > > Dinkumware, Ltd.
> > > http://www.dinkumware.com

> >
> > True that I can't peek, but in inserting a value, wouldn't it be
> > beneficial to know the type in case someone wants to use parameterized
> > constructor / enforce parameterized contruction.

>
> It might be, but that's not a requirement for output iterators.
>
> > What I meant is as follows:
> >
> > // following std::copy
> > template <typename InIt, typename OutIt>
> > OutIt copy_to_container(InIt begin, InIt end, OutIt result)
> > {
> > // want to use value_type for output
> > *result = OutIt::value_type(begin, end);

>
> Shouldn't there be a loop in here somewhere?


No loop here, result is a container of a container, and I want to copy
elements from begin to end as an element of result. The examples
shows the usage (this is just a simplification).

>
> > return ++result;
> > }
> >
> > Using append:
> >
> > char s[] = "abc";
> > vector<string> vs(1); // contain 1 string
> > vector<vector<char> > vvc(1);
> >
> > copy_to_container(s, s+1, vs.begin()); // ok
> > copy_to_container(s, s+1, vvc.begin()); // ok
> > copy_to_container(s, s+2, back_inserter(vs)); // fail to compile
> >
> >
> > If the value_type of back_inserter is defined as the type of its
> > encapsulating container, we can utilize that property.
> >
> > Since this is not possible, please advise on alternative
> > implementation that is as flexible.

>
> If you want to use additional type information to constrain
> assignments to an output iterator, you'll have to supply it
> by a different channel.
>


Naturally, the solution I came up w/ is to derived
back_insert_with_type from back_inserter and define the value_type as
the type of the container. Please give your opinion on this solution.
If possible, please provide ideas for alternative solutions to my
problem. Thanks.
 
Reply With Quote
 
Chyi Pin Lim
Guest
Posts: n/a
 
      12-08-2003
Thank you for posting such a descriptive explanation.

> > >
> > > > Why is the type for back_insert_iterator void and not the type of its
> > > > encapsulating container?
> > >
> > > Because it's an output iterator, which is a pure sink. (You can't
> > > peek at any of the things stored in the sequence it controls.)
> > >
> > > P.J. Plauger
> > > Dinkumware, Ltd.
> > > http://www.dinkumware.com

> > I agree with P.J.Plauger

>
> What I thought is:
> if an output iterator exposes its value_type to the user,then someone
> who use it like this:
> template<typename OutIte>
> void f(OutIte ite){
> OutIte::value_type value=*ite; //should it be compiled??
> ...
> }
> will expect that such a function can be compiled,which exactly can't
> be(you can't get the value that refered to by an output iterator).
> Now consider what really happened here:
> users thought that 'operator *' returns a value of 'value_type',so if
> the 'value_type' was some concrete class or primitive type,the
> function template above should be compiled according to the semantic
> it has.


As an output iterator, it is expected that one should not read
from it, but allow to write to the iterator. As such,
OutIt::value_type value = *it; // should not compile
however,
I was thinking,
OutIt::value_type value = *in_it; // if *in_it is convertible to
OutIt::value_type, then it should allow to compile
*out_it = value; // ok

>
> of course you can let 'operator *' returns a no-meaning value of a
> no-meaning type,such as a proxy,or *this(as the ostream_iterator
> actually did),but note that what the value_type is,it isn't the return
> type of 'operator *',
> So it's inconsistent!!!!
>
> But by declaring the value_type as 'void',it can avoid this kind of
> inconsistent----because *ite returns 'void',so you actually can't
> cache it anywhere.In other ways,the 'void' value_type implies that you
> actually coudn't get the value_type,and you shouldn't care about it
> either.With that being the case,you can write "*ite=value".
> What really important is semantic.
>


I see your point and agree w/ your argument. However, defining
the value_type as the type of the container doesn't break the semantic
usage.

we still do not allow:
OutIt::value_type v = *out_it;
but allow:
*out_it = v;

> The situation that you present may rarely happen,I think.
> If it happened,like P.J.Plauger said,you'll have to supply it
> by a different channel.

 
Reply With Quote
 
P.J. Plauger
Guest
Posts: n/a
 
      12-08-2003
"Chyi Pin Lim" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed) om...

> > > If the value_type of back_inserter is defined as the type of its
> > > encapsulating container, we can utilize that property.
> > >
> > > Since this is not possible, please advise on alternative
> > > implementation that is as flexible.

> >
> > If you want to use additional type information to constrain
> > assignments to an output iterator, you'll have to supply it
> > by a different channel.
> >

>
> Naturally, the solution I came up w/ is to derived
> back_insert_with_type from back_inserter and define the value_type as
> the type of the container. Please give your opinion on this solution.
> If possible, please provide ideas for alternative solutions to my
> problem. Thanks.


That sounds like one version of the solution I suggested. Go with it.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com


 
Reply With Quote
 
ppLiu_china
Guest
Posts: n/a
 
      12-11-2003
> we still do not allow:
> OutIt::value_type v = *out_it;
> but allow:
> *out_it = v;
>


Really?Consider the ostream_iterator<>,which typically is implemented as following:
//coped from STL of VC.NET
template<...>
class ostream_iterator{
public:
ostream_iterator<_Ty, _Elem, _Traits>& operator*()
{
return (*this); //note the return type
}
}
and give you a simply class:
class Swap
{
public:
Swap(const ostream_iterator<Swap>&){} #1
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //note the parameter type
...
};
Now,Consider the following code:
int main()
{
...
ostream_iterator<Swap> os_ite=someOstream.begin(); //we will read 'Swap'
//from 'someOstream'
ostream_iterator<Swap>::value_type value =
*os_ite; #2 //if the 'value_type'
//is 'Swap',what will
//happen here?
return 0;
}
At #2,if 'value_type' was defined as Swap,then #2 is the same as:
Swap value=*os_ite; #3
But,*os_ite returns a reference to itself,that is ostream_iterator<Swap>&,which
was then used as the parameter type of Swap's constructor(see #1);

So compiler will let #3 go!
Is that what we want?

By defining value_type as 'void'(a type that means 'nothing'),we can avoid this.
 
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
output_iterator_tag and back_insert_iterator Rares Vernica C++ 2 06-21-2008 06:06 AM
iterator_traits::value_type on back_insert_iterator - returns void anto.anish@gmail.com C++ 14 02-12-2008 11:14 AM
why both value_type and reference Andrew C++ 4 03-07-2006 07:05 PM
sorting maps according to their value_type cesco C++ 5 02-10-2006 12:04 PM
Purpose of iterator_traits::value_type chris C++ 8 12-10-2004 04:02 PM



Advertisments