473,397 Members | 1,985 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,397 software developers and data experts.

value_type of a back_insert_iterator

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
9 1613
"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.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
"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.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
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.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
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
"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
> 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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

8
by: chris | last post by:
I tried to post this to comp.std.c++ some time ago, but for some reason I aren't getting any automatic confirmation. I thought I would therefore post it here. Some time ago I submitted what is...
4
by: Andrew | last post by:
Hello: Can someone please elaborate on why the member types 'value_type', 'reference', and 'const_reference' are all defined in a standard STL container. Why not just define 'value_type' and...
6
by: Daniel T. | last post by:
The line marked (1) below compiles fine and does exactly what I would expect, but the line marked (2) does not compile at all on my system. error: variable or field 'bar' declared void My...
4
by: FabioAng | last post by:
Assuming I have this function: template<typename OutputIterator> void copy(const char* input, OutputIterator result) { while ( *input != NULL ) { *result = *input; ++result; ++input;
3
by: George2 | last post by:
Hello everyone, I think the value_type of vector<intshould be int and the value_type of vector<intshould be int*. But I am not 100% sure, 1. how to write a program to verify this idea; 2....
3
by: massysett | last post by:
I'm puzzled about part of the standard. 23.1 states that items stored in a container must be assignable. Therefore, the items in a map--that is, std::pair<const Key, valuemust be assignable....
1
by: antoanish | last post by:
Hello, My Requirement is 1. Copy data from iterator to an array ( array should be created dynamically within the function based on data_type of the data held by the iterator /container. )...
2
by: Rares Vernica | last post by:
Hello, I am trying to write a generic function that can read data from a file and store it in a container. I defined the following function: template<class T> void readBinaryFile( const...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.