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
}; 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
"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.
"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
"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 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.
"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.
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.
"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
> 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. This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
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...
|
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...
|
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...
|
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;
|
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....
|
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....
|
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. )...
|
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...
|
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...
|
by: nemocccc |
last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
|
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...
|
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,...
|
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...
|
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...
|
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...
|
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...
|
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,...
| |