 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Toby Reyelts Guest
|
Posted: Tue Dec 16, 2003 1:05 am Post subject: Why doesn't vector( size_type, const T& ) work? |
|
|
I want to initialize a vector of pointers so that all of its elements
are null, so this is the code I write:
class A {
};
// Create a vector of 10 A pointers, all set to null
vector<A*> v( 10, 0 );
but both VC++ 7.1 and Comeau C++ give me a diagnostic saying that an
int can not be converted to an A*.
Here's what Comeau says:
"stl_algobase.h", line 452: error: a value of type "int" cannot be
assigned
to an entity of type "A *"
*__first = __value;
^
detected during instantiation of "_OutputIter
std::fill_n(_OutputIter, _Size, const _Tp &) [with
_OutputIter=A **, _Size=int, _Tp=int]"
Since I can see the call to fill_n(), it looks like the correct
constructor is being called - vector( size_type, const T& ). Why
doesn't the compiler see 0 as an A* initialized to null rather than as
an int that is 0? I can just take up an extra line of code by
declaring a dummy A*, setting it to 0, then passing that value to the
vector constructor - but that seems quite verbose.
God bless,
-Toby Reyelts
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
John Potter Guest
|
Posted: Tue Dec 16, 2003 10:58 am Post subject: Re: Why doesn't vector( size_type, const T& ) work? |
|
|
On 15 Dec 2003 20:05:11 -0500, [email]toby (AT) reyelts (DOT) com[/email] (Toby Reyelts) wrote:
| Quote: | I want to initialize a vector of pointers so that all of its elements
are null, so this is the code I write:
class A {
};
// Create a vector of 10 A pointers, all set to null
vector<A*> v( 10, 0 );
but both VC++ 7.1 and Comeau C++ give me a diagnostic saying that an
int can not be converted to an A*.
|
This is beautiful.
| Quote: | Here's what Comeau says:
"stl_algobase.h", line 452: error: a value of type "int" cannot be
assigned
to an entity of type "A *"
*__first = __value;
^
detected during instantiation of "_OutputIter
std::fill_n(_OutputIter, _Size, const _Tp &) [with
_OutputIter=A **, _Size=int, _Tp=int]"
Since I can see the call to fill_n(), it looks like the correct
constructor is being called - vector( size_type, const T& ).
|
That is not the constructor being called because the types do not
match exactly. There is a better match for a different ctor.
| Quote: | Why
doesn't the compiler see 0 as an A* initialized to null rather than as
an int that is 0?
|
Because at that point it is an int with value zero not the literal 0.
| Quote: | I can just take up an extra line of code by
declaring a dummy A*, setting it to 0, then passing that value to the
vector constructor - but that seems quite verbose.
|
Just cast it in the call.
vector<A*> v( 10, static_cast<A*>(0) );
You could also fix the problem by casting the other argument.
vector<A*> v( vector<A*>::size_type(10), 0 );
Neither of the parameters wants an int, but you asked for a ctor with
two ints as arguments. There is one which matches perfectly and would
work for two iterators. That templated ctor with two of the same type
parameters matches those two ints perfectly.
Now the standard 23.1.1/9 says that your code must compile.
| Quote: | template <class InputIterator
X (InputIterator f, InputIterator l, const Allocator& a = Allocator())
shall have the same effect as
X (static_cast
static_cast
if InputIterator is an integral type.
|
Note that it states that the ctor call must have the same effect as the
other ctor call with the arguments cast to appropriate types. Both of
your compilers and g++ use internal magic to almost make it work right.
The problem is that they let the ctor be instantiated and then try to
work with the integer with value 0. If the casts are done in the call
as the required effect, there would be a static_cast of a literal 0 to
a pointer which is valid.
The standard gives one complex way to handle this which might work and
hints that there are other ways which are simpler. In this case, the
simple way missed a special case.
John
P.S. I can see Howard in pain from laughing so hard at this. Hopefully
no broken ribs. :)
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
James Dennett Guest
|
Posted: Tue Dec 16, 2003 11:01 am Post subject: Re: Why doesn't vector( size_type, const T& ) work? |
|
|
Toby Reyelts wrote:
| Quote: | I want to initialize a vector of pointers so that all of its elements
are null, so this is the code I write:
class A {
};
// Create a vector of 10 A pointers, all set to null
vector<A*> v( 10, 0 );
but both VC++ 7.1 and Comeau C++ give me a diagnostic saying that an
int can not be converted to an A*.
Here's what Comeau says:
"stl_algobase.h", line 452: error: a value of type "int" cannot be
assigned
to an entity of type "A *"
*__first = __value;
^
detected during instantiation of "_OutputIter
std::fill_n(_OutputIter, _Size, const _Tp &) [with
_OutputIter=A **, _Size=int, _Tp=int]"
Since I can see the call to fill_n(), it looks like the correct
constructor is being called - vector( size_type, const T& ).
|
I suspect that isn't so. Indeed, you note below that if you
*do* pass an A* then the right constructor is called and does
the right thing.
| Quote: | Why
doesn't the compiler see 0 as an A* initialized to null rather than as
an int that is 0? I can just take up an extra line of code by
declaring a dummy A*, setting it to 0, then passing that value to the
vector constructor - but that seems quite verbose.
|
You could just write
std::vector<A*> v(10, static_cast<void*>(0));
It sounds like you've been caught by some wording in
the standard that is there to "do the right thing"
with the templated constructor that takes two values
of the same type: in your case, both ints. This wording
is there so that the ints aren't treated as iterators --
but in the case you have, you don't want them treated as
integral values either, and there the standard may well
fall short.
-- James.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
jean Davy Guest
|
Posted: Tue Dec 16, 2003 11:17 am Post subject: Re: Why doesn't vector( size_type, const T& ) work? |
|
|
You should type
vector<A*> v( 10 );
as by default the default value used to initialize is NULL
"Toby Reyelts" <toby (AT) reyelts (DOT) com> a écrit dans le message de
news:27f8bc71.0312151343.3559309a (AT) posting (DOT) google.com...
| Quote: | I want to initialize a vector of pointers so that all of its elements
are null, so this is the code I write:
class A {
};
// Create a vector of 10 A pointers, all set to null
vector<A*> v( 10, 0 );
but both VC++ 7.1 and Comeau C++ give me a diagnostic saying that an
int can not be converted to an A*.
Here's what Comeau says:
"stl_algobase.h", line 452: error: a value of type "int" cannot be
assigned
to an entity of type "A *"
*__first = __value;
^
detected during instantiation of "_OutputIter
std::fill_n(_OutputIter, _Size, const _Tp &) [with
_OutputIter=A **, _Size=int, _Tp=int]"
Since I can see the call to fill_n(), it looks like the correct
constructor is being called - vector( size_type, const T& ). Why
doesn't the compiler see 0 as an A* initialized to null rather than as
an int that is 0? I can just take up an extra line of code by
declaring a dummy A*, setting it to 0, then passing that value to the
vector constructor - but that seems quite verbose.
|
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Andreas Mueller Guest
|
Posted: Tue Dec 16, 2003 11:25 am Post subject: Re: Why doesn't vector( size type, const T& ) work? |
|
|
Toby Reyelts wrote:
| Quote: | I want to initialize a vector of pointers so that all of its elements
are null, so this is the code I write:
class A {
};
// Create a vector of 10 A pointers, all set to null
vector<A*> v( 10, 0 );
but both VC++ 7.1 and Comeau C++ give me a diagnostic saying that an
int can not be converted to an A*.
[snip] |
Hi,
looks like the compiler has problems to deduce that 0 means an A* with
the value of 0. On VC7 with its onboard STL, it will choose the wrong
ctor (vector(iterator, iterator) ). I don't know if that is legal or
not, but a simple workaround on VC7.1 is:
std::vector<A*> vA(10, static_cast<A*>(0));
It propably will work for other compilers, too.
HTH,
Andy
--
To mail me directly, remove the NO*SPAM parts in
NO*SPAMxmen40 (AT) gmx (DOT) netNO*SPAM
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Gareth Stockwell Guest
|
Posted: Tue Dec 16, 2003 11:27 am Post subject: Re: Why doesn't vector( size_type, const T& ) work? |
|
|
| Quote: | I want to initialize a vector of pointers so that all of its elements
are null, so this is the code I write:
class A {
};
// Create a vector of 10 A pointers, all set to null
vector<A*> v( 10, 0 );
|
Toby,
GCC 3.3.1 also disagrees with this. You're right - creating and
passing an A* solves the problem, but so does a cast:
std::vector<A*> v(10, static_cast<A*>(0));
Gareth
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Francis Glassborow Guest
|
Posted: Tue Dec 16, 2003 3:27 pm Post subject: Re: Why doesn't vector( size_type, const T& ) work? |
|
|
In article <27f8bc71.0312151343.3559309a (AT) posting (DOT) google.com>, Toby
Reyelts <toby (AT) reyelts (DOT) com> writes
| Quote: | Since I can see the call to fill_n(), it looks like the correct
constructor is being called - vector( size_type, const T& ). Why
doesn't the compiler see 0 as an A* initialized to null rather than as
an int that is 0? I can just take up an extra line of code by
declaring a dummy A*, setting it to 0, then passing that value to the
vector constructor - but that seems quite verbose.
|
Or you could write:
std::vector<A*> v(10, (A*)0);
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
or http://www.robinton.demon.co.uk
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Tue Dec 16, 2003 6:06 pm Post subject: Re: Why doesn't vector( size_type, const T& ) work? |
|
|
[email]toby (AT) reyelts (DOT) com[/email] (Toby Reyelts) wrote in message
news:<27f8bc71.0312151343.3559309a (AT) posting (DOT) google.com>...
| Quote: | I want to initialize a vector of pointers so that all of its elements
are null, so this is the code I write:
class A {
};
// Create a vector of 10 A pointers, all set to null
vector<A*> v( 10, 0 );
but both VC++ 7.1 and Comeau C++ give me a diagnostic saying that an
int can not be converted to an A*.
|
Interesting case.
| Quote: | Here's what Comeau says:
"stl_algobase.h", line 452: error: a value of type "int" cannot be
assigned
to an entity of type "A *"
*__first = __value;
^
detected during instantiation of "_OutputIter
std::fill_n(_OutputIter, _Size, const _Tp &) [with
_OutputIter=A **, _Size=int, _Tp=int]"
Since I can see the call to fill_n(), it looks like the correct
constructor is being called - vector( size_type, const T& ).
|
If the compiler and the library are conformant, the constructor being
called is the templated:
template< typename FwdIter >
vector( FwdIter begin, FwdIter end );
with FwdIter resolving to int. This is a special case, and it is
required to have the same effect as:
vector( static_cast< size_type >( begin ),
static_cast< value_type >( end ) ) ;
had been called.
The problem here is that this will take place within the constructor
itself, using the parameters of the constructor. And end (or whatever
the implementation calls it) is NOT a constant integral expression, and
thus is NOT a null pointer constant, even though it has been initialized
by the constant integral expression 0.
But that's an explination of what the implementation probably does. The
standard is quite clear -- in your case, the initialization is required
to have the same effect as:
vector::vector< A* >( static_cast< size_t >( 10 ),
static_cast< A* >( 0 ) ) ;
Which, of course, is perfectly legal, and initializes the vector with 10
null pointers. So there is a bug in both implementations. (On the
other hand, I'm not sure that what the standard requires here is even
implementable.)
| Quote: | Why doesn't the compiler see 0 as an A* initialized to null rather
than as an int that is 0?
|
Because by the time it is deciding what to do, it is inside the
constructor, and it sees a parameter. And a parameter can never be a
constant integral expression.
| Quote: | I can just take up an extra line of code by declaring a dummy A*,
setting it to 0, then passing that value to the vector constructor -
but that seems quite verbose.
|
Wouldn't it be easier just to say what you mean :
vector<A*> v( 10, static_cast< A* >( 0 ) ) ;
--
James Kanze GABI Software mailto:kanze (AT) gabi-soft (DOT) fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Dhruv Guest
|
Posted: Tue Dec 16, 2003 6:22 pm Post subject: Re: Why doesn't vector( size_type, const T& ) work? |
|
|
On Mon, 15 Dec 2003 20:05:11 -0500, Toby Reyelts wrote:
| Quote: | I want to initialize a vector of pointers so that all of its elements
are null, so this is the code I write:
class A {
};
// Create a vector of 10 A pointers, all set to null
vector<A*> v( 10, 0 );
but both VC++ 7.1 and Comeau C++ give me a diagnostic saying that an
int can not be converted to an A*.
|
This raises a new question... Is it legal to create a pointer A* that
holds the literal zero 0? Yes, of course it is. But then how come, the
implmentations fall short of recognizing this fact?
Modify line 365 of stl_vector.h for libstdc++ to read:
_M_finish = uninitialized_fill_n(_M_start, __n, _Tp(__value));
I do not know whether it is conformant for an implementation to make 2
copies of the __value parameter passed to the constructor?
Or for that matter, even this statement will fail:
v.insert (v.end (), 10, 0);
Regards,
-Dhruv.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Howard Hinnant Guest
|
Posted: Tue Dec 16, 2003 6:25 pm Post subject: Re: Why doesn't vector( size_type, const T& ) work? |
|
|
In article <jimstvcth5qlpmh5nhov7eaej3sndmi4bo (AT) 4ax (DOT) com>,
John Potter <jpotter (AT) falcon (DOT) lhup.edu> wrote:
| Quote: | P.S. I can see Howard in pain from laughing so hard at this. Hopefully
no broken ribs.
|
I'll be ok. <chuckle ... HAHAHAHA Ouch! Ouch! ...chuckle ... HAHAHAHA
Ouch! Ouch! ...chuckle ... HAHAHAHA Ouch! Ouch! ...> :-)
-Howard
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
John Potter Guest
|
Posted: Tue Dec 16, 2003 9:21 pm Post subject: Re: Why doesn't vector( size_type, const T& ) work? |
|
|
On 16 Dec 2003 13:22:44 -0500, "Dhruv" <dhruvbird (AT) gmx (DOT) net> wrote:
| Quote: | Modify line 365 of stl_vector.h for libstdc++ to read:
_M_finish = uninitialized_fill_n(_M_start, __n, _Tp(__value));
I do not know whether it is conformant for an implementation to make 2
copies of the __value parameter passed to the constructor?
|
Placing random reinterpret_casts in standard libraries is not well
advised. _Tp(__value) is a cast expression equivalent to (_Tp)__value
and since _Tp is a pointer type and __value is type int, that is
reinterpret_cast<_Tp>(__value)
| Quote: | Or for that matter, even this statement will fail:
v.insert (v.end (), 10, 0);
|
It fails because the implementation has a bug. Let someone who knows
what they are doing try to fix the implementation. Work around the
bug by being explicit.
v.insert(v.end(), 10, static_cast<A*>(0));
John
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Francis Glassborow Guest
|
Posted: Tue Dec 16, 2003 9:23 pm Post subject: Re: Why doesn't vector( size_type, const T& ) work? |
|
|
In article <pan.2003.12.16.14.30.25.216948 (AT) gmx (DOT) net>, Dhruv
<dhruvbird (AT) gmx (DOT) net> writes
| Quote: | This raises a new question... Is it legal to create a pointer A* that
holds the literal zero 0? Yes, of course it is. But then how come, the
implmentations fall short of recognizing this fact?
|
I wonder why you think that? Unless you mean that you are allowed to use
write to the pointer storage as an array of char. If address zero is not
owned by your process it is perfectly OK for the OS to close your
process down anyway it chooses so to do.
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
or http://www.robinton.demon.co.uk
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Dhruv Guest
|
Posted: Wed Dec 17, 2003 10:03 am Post subject: Re: Why doesn't vector( size_type, const T& ) work? |
|
|
On Tue, 16 Dec 2003 16:21:21 -0500, John Potter wrote:
| Quote: | On 16 Dec 2003 13:22:44 -0500, "Dhruv" <dhruvbird (AT) gmx (DOT) net> wrote:
Modify line 365 of stl_vector.h for libstdc++ to read:
_M_finish = uninitialized_fill_n(_M_start, __n, _Tp(__value));
I do not know whether it is conformant for an implementation to make 2
copies of the __value parameter passed to the constructor?
Placing random reinterpret_casts in standard libraries is not well
advised. _Tp(__value) is a cast expression equivalent to (_Tp)__value
and since _Tp is a pointer type and __value is type int, that is
reinterpret_cast<_Tp>(__value)
|
Ok. I thought that suppose you have:
char *A;
A = char* (0);//Amounts to reinterpret cast,
but:
struct X {
X (int);
};
X x;
x = X(0)//Valid construction? Isn't this legal?
Regards,
-Dhruv.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Dhruv Guest
|
Posted: Wed Dec 17, 2003 10:13 am Post subject: Re: Why doesn't vector( size_type, const T& ) work? |
|
|
On Tue, 16 Dec 2003 05:58:54 -0500, John Potter wrote:
| Quote: | Note that it states that the ctor call must have the same effect as the
other ctor call with the arguments cast to appropriate types. Both of
your compilers and g++ use internal magic to almost make it work right.
The problem is that they let the ctor be instantiated and then try to
work with the integer with value 0. If the casts are done in the call
as the required effect, there would be a static_cast of a literal 0 to
a pointer which is valid.
|
Not quite exactly, because once the InputIterator overload has been
selected, then InputIterator gets int, and that's where the problem starts
I guess. Now, when passing down to the real ctor, type has been deduced to
be int, so static_cast<pointer_type> (integer) doesn't quite work out
| Quote: | The standard gives one complex way to handle this which might work and
hints that there are other ways which are simpler. In this case, the
simple way missed a special case.
John
P.S. I can see Howard in pain from laughing so hard at this. Hopefully
no broken ribs.
|
I guess the restricted template technique that Howard Hinnant has proposed
would work beautifully here.
Regards,
-Dhruv.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Wed Dec 17, 2003 4:31 pm Post subject: Re: Why doesn't vector( size type, const T& ) work? |
|
|
"Andreas Mueller" <me (AT) privacy (DOT) net> wrote
| Quote: | Toby Reyelts wrote:
I want to initialize a vector of pointers so that all of its
elements are null, so this is the code I write:
class A {
};
// Create a vector of 10 A pointers, all set to null
vector<A*> v( 10, 0 );
but both VC++ 7.1 and Comeau C++ give me a diagnostic saying that
an int can not be converted to an A*.
[snip]
looks like the compiler has problems to deduce that 0 means an A* with
the value of 0. On VC7 with its onboard STL, it will choose the wrong
ctor (vector(iterator, iterator) ).
|
And just which constructor should it choose? When instantiated with
iterator == int, vector(iterator,iterator) is an exact match. It's hard
to see another constructor which would be better than an exact match.
| Quote: | I don't know if that is legal or not, but a simple workaround on VC7.1
is:
std::vector<A*> vA(10, static_cast<A*>(0));
It propably will work for other compilers, too.
|
In general, it is preferable most of the time to specify conversions
explicitly, rather than counting on implicit conversions. when dealing
with templates and/or function overloads, it is even more important.
That said, I think that we really do need a null pointer constant that
isn't an int.
--
James Kanze GABI Software mailto:kanze (AT) gabi-soft (DOT) fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|