By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
445,852 Members | 2,219 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 445,852 IT Pros & Developers. It's quick & easy.

value_type of a back_insert_iterator

P: n/a
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
};
Jul 22 '05 #1
Share this Question
Share on Google+
9 Replies


P: n/a
"Chyi Pin Lim" <ni*****@hotmail.com> wrote in message
news:c9**************************@posting.google.c 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
Jul 22 '05 #2

P: n/a
"P.J. Plauger" <pj*@dinkumware.com> wrote in message news:<kA***************@nwrddc01.gnilink.net>...
"Chyi Pin Lim" <ni*****@hotmail.com> wrote in message
news:c9**************************@posting.google.c 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.
Jul 22 '05 #3

P: n/a
"Chyi Pin Lim" <ni*****@hotmail.com> wrote in message
news:c9**************************@posting.google.c om...
"P.J. Plauger" <pj*@dinkumware.com> wrote in message news:<kA***************@nwrddc01.gnilink.net>...
"Chyi Pin Lim" <ni*****@hotmail.com> wrote in message
news:c9**************************@posting.google.c 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
Jul 22 '05 #4

P: n/a
"P.J. Plauger" <pj*@dinkumware.com> wrote in message news:<kA***************@nwrddc01.gnilink.net>...
"Chyi Pin Lim" <ni*****@hotmail.com> wrote in message
news:c9**************************@posting.google.c 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
Jul 22 '05 #5

P: n/a
qi*******@sina.com (ppLiu_china) wrote in message news:<19**************************@posting.google. com>...
"P.J. Plauger" <pj*@dinkumware.com> wrote in message news:<kA***************@nwrddc01.gnilink.net>...
"Chyi Pin Lim" <ni*****@hotmail.com> wrote in message
news:c9**************************@posting.google.c 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.
Jul 22 '05 #6

P: n/a
"P.J. Plauger" <pj*@dinkumware.com> wrote in message news:<VK*****************@nwrddc02.gnilink.net>...
"Chyi Pin Lim" <ni*****@hotmail.com> wrote in message
news:c9**************************@posting.google.c om...
"P.J. Plauger" <pj*@dinkumware.com> wrote in message news:<kA***************@nwrddc01.gnilink.net>...
"Chyi Pin Lim" <ni*****@hotmail.com> wrote in message
news:c9**************************@posting.google.c 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.
Jul 22 '05 #7

P: n/a
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.

Jul 22 '05 #8

P: n/a
"Chyi Pin Lim" <ni*****@hotmail.com> wrote in message
news:c9**************************@posting.google.c 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
Jul 22 '05 #9

P: n/a
> 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.
Jul 22 '05 #10

This discussion thread is closed

Replies have been disabled for this discussion.