template <class OutputIterator, class Size, class T>
void fill_n (OutputIterator first, Size n, const T& value)
{
while (n-- 0) *first++ = value;
}
If Size must be convertible to an integral type is this not an
implementation that excludes passing an enum value as the second
parameter? An enum value is convertible to an integral type so the
implementation does not match the specification.
Posted Via Usenet.com Premium Usenet Newsgroup Services
----------------------------------------------------------
** SPEED ** RETENTION ** COMPLETION ** ANONYMITY **
---------------------------------------------------------- http://www.usenet.com 26 1433
Fraser Ross wrote:
template <class OutputIterator, class Size, class T>
void fill_n (OutputIterator first, Size n, const T& value)
{
while (n-- 0) *first++ = value;
}
If Size must be convertible to an integral type is this not an
implementation that excludes passing an enum value as the second
parameter? An enum value is convertible to an integral type so the
implementation does not match the specification.
Correct. Where did you find this one? A better way would be to make
it
void fill_n (OutputIterator first, Size n_arg, const T& value)
{
size_t n = n_arg; ...
, probably.
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Victor Bazarov wrote:
Correct. Where did you find this one?
I found the same issue in gcc's STL. Indeed sgi's STL documentation
defines the requirement to be that Size must be an integral type.
Jens
Jens Theisen wrote:
Victor Bazarov wrote:
>Correct. Where did you find this one?
I found the same issue in gcc's STL. Indeed sgi's STL documentation
defines the requirement to be that Size must be an integral type.
The requirement now exists in the Standard (since 1997), so any C++
standard library implementation that doesn't use a local variable is
not going to work with enums, as the OP hinted.
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
I'm using the Rogue Wave STL with BCB6.
Fraser.
Posted Via Usenet.com Premium Usenet Newsgroup Services
----------------------------------------------------------
** SPEED ** RETENTION ** COMPLETION ** ANONYMITY **
---------------------------------------------------------- http://www.usenet.com
Jens Theisen wrote:
Victor Bazarov wrote:
>Correct. Where did you find this one?
I found the same issue in gcc's STL. Indeed sgi's STL documentation
defines the requirement to be that Size must be an integral type.
But the standard does say otherwise:
[25.2.5]
template<class ForwardIterator, class T>
void fill(ForwardIterator first, ForwardIterator last, const T& value);
template<class OutputIterator, class Size, class T>
void fill_n(OutputIterator first, Size n, const T& value);
Requires: Type T is Assignable (23.1), Size is convertible to an integral
type (4.7, 12.3).
Effects: Assigns value through all the iterators in the range [first,
last)or [first, first +n).
Best
Kai-Uwe Bux
Victor Bazarov wrote:
The requirement now exists in the Standard (since 1997), so any C++
standard library implementation that doesn't use a local variable is
not going to work with enums, as the OP hinted.
The standard I'm looking at was released 1998. And after all, it's
C++98, isn't it? How come that I still have the "convertible" variant?
Jens
"Victor Bazarov" <v.********@comAcast.netskrev i meddelandet
news:yq******************************@comcast.com. ..
Fraser Ross wrote:
> template <class OutputIterator, class Size, class T> void fill_n (OutputIterator first, Size n, const T& value) { while (n-- 0) *first++ = value; }
If Size must be convertible to an integral type is this not an implementation that excludes passing an enum value as the second parameter? An enum value is convertible to an integral type so the implementation does not match the specification.
Correct. Where did you find this one? A better way would be to
make
it
void fill_n (OutputIterator first, Size n_arg, const T& value)
{
size_t n = n_arg; ...
, probably.
That would fail for negative values instead.
This is tricky. :-)
Bo Persson
Bo Persson wrote:
"Victor Bazarov" <v.********@comAcast.netskrev i meddelandet
news:yq******************************@comcast.com. ..
>Fraser Ross wrote:
>> template <class OutputIterator, class Size, class T> void fill_n (OutputIterator first, Size n, const T& value) { while (n-- 0) *first++ = value; }
If Size must be convertible to an integral type is this not an implementation that excludes passing an enum value as the second parameter? An enum value is convertible to an integral type so the implementation does not match the specification.
Correct. Where did you find this one? A better way would be to make it
void fill_n (OutputIterator first, Size n_arg, const T& value) { size_t n = n_arg; ...
, probably.
That would fail for negative values instead.
Is that really a problem? Is the behavior of std::fill_n even defined by
the standard when n_arg is negative?
--
Clark S. Cox III cl*******@gmail.com
"Clark S. Cox III" <cl*******@gmail.comskrev i meddelandet
news:12*************@corp.supernews.com...
Bo Persson wrote:
>"Victor Bazarov" <v.********@comAcast.netskrev i meddelandet news:yq******************************@comcast.com ...
>>Fraser Ross wrote: template <class OutputIterator, class Size, class T> void fill_n (OutputIterator first, Size n, const T& value) { while (n-- 0) *first++ = value; }
If Size must be convertible to an integral type is this not an implementation that excludes passing an enum value as the second parameter? An enum value is convertible to an integral type so the implementation does not match the specification. Correct. Where did you find this one? A better way would be to make it
void fill_n (OutputIterator first, Size n_arg, const T& value) { size_t n = n_arg; ...
, probably. That would fail for negative values instead.
Is that really a problem? Is the behavior of std::fill_n even
defined by
the standard when n_arg is negative?
Yes, it is. The committee has specifically rejected undefined
behaviour for that case. http://www.open-std.org/jtc1/sc22/wg...n2025.html#426
Bo Persson
Jens Theisen wrote:
Victor Bazarov wrote:
>The requirement now exists in the Standard (since 1997), so any C++ standard library implementation that doesn't use a local variable is not going to work with enums, as the OP hinted.
The standard I'm looking at was released 1998. And after all, it's
C++98, isn't it? How come that I still have the "convertible" variant?
I must have misunderstood. The Standard says "convertible". However,
the implementation that makes direct use of the argument and tries to
decrement it using -- is not going to work with a "convertible" type.
It will only work with true integral type.
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
A suitable implementation is easy enough to make. It surprises me how
much library code uses pre increment and decrement operators. They can
be less efficient.
Fraser.
void fill_n (OutputIterator first, Size n_arg, const T& value)
{
size_t n = n_arg; ...
, probably.
That would fail for negative values instead.
This is tricky. :-)
Bo Persson
Posted Via Usenet.com Premium Usenet Newsgroup Services
----------------------------------------------------------
** SPEED ** RETENTION ** COMPLETION ** ANONYMITY **
---------------------------------------------------------- http://www.usenet.com
I meant to type post not pre.
"Fraser Ross"
It surprises me how
much library code uses pre increment and decrement operators. They
can
be less efficient.
Posted Via Usenet.com Premium Usenet Newsgroup Services
----------------------------------------------------------
** SPEED ** RETENTION ** COMPLETION ** ANONYMITY **
---------------------------------------------------------- http://www.usenet.com
Fraser Ross wrote:
A suitable implementation is easy enough to make.
Please don't top-post. Your replies belong following or interspersed
with properly trimmed quotes. See the majority of other posts in the
newsgroup, or the group FAQ list:
<http://www.parashift.com/c++-faq-lite/how-to-post.html>
Brian
"Fraser Ross" <fraserATmembers.v21.co.ukskrev i meddelandet
news:11***********@sp6iad.superfeed.net...
>A suitable implementation is easy enough to make. It surprises me how
much library code uses pre increment and decrement operators. They
can
be less efficient.
Fraser.
I don't think it is obvious how to select a proper integral type for
n, when you don't know what type Size might be. In this case, if n_arg
happens to be negative, converting it to size_t will not work well.
If Size happens to be a class type with a user defined convertion
operator, how do we know what type(s) it will convert to? Signed, or
unsigned?
Bo Persson
>
void fill_n (OutputIterator first, Size n_arg, const T& value)
{
size_t n = n_arg; ...
, probably. That would fail for negative values instead.
This is tricky. :-)
Bo Persson
Bo Persson posted:
I don't think it is obvious how to select a proper integral type for
n, when you don't know what type Size might be. In this case, if n_arg
happens to be negative, converting it to size_t will not work well.
Perhaps something like this:
(It doesn't compile but you get the idea)
enum MyEnum { a,b,c,d,e,f };
template<class T, bool is_signed = ((T)-1 < 0)>
void Func(T arg);
template<class T>
void Func<T,true>(T arg)
{
long i = arg;
}
template<class T>
void Func<T,false>(T arg)
{
long unsigned i = arg;
}
int main()
{
MyEnum obj;
Func(obj);
}
--
Frederick Gotham
Bo Persson wrote:
>
"Fraser Ross" <fraserATmembers.v21.co.ukskrev i meddelandet
news:11***********@sp6iad.superfeed.net...
>>A suitable implementation is easy enough to make. It surprises me how much library code uses pre increment and decrement operators. They can be less efficient.
Fraser.
I don't think it is obvious how to select a proper integral type for
n, when you don't know what type Size might be. In this case, if n_arg
happens to be negative, converting it to size_t will not work well.
If Size happens to be a class type with a user defined convertion
operator, how do we know what type(s) it will convert to? Signed, or
unsigned?
Who says that it is necessary to make a guess as to whether Size converts to
signed or unsigned? What about :
template < typename OutIter, typename Size, typename T >
void fill_n ( OutIter first, Size n, const T & value ) {
for ( std::size_t i = 0; i < n; ++i ) {
*first = value;
++first;
}
}
One could use specialization tricks to save the local variable when Size is
an arithmetic type.
> void fill_n (OutputIterator first, Size n_arg, const T& value) { size_t n = n_arg; ...
, probably.
That would fail for negative values instead.
This is tricky. :-)
Best
Kai-Uwe Bux
"Frederick Gotham" <fg*******@SPAM.comskrev i meddelandet
news:1J*******************@news.indigo.ie...
Bo Persson posted:
>I don't think it is obvious how to select a proper integral type for n, when you don't know what type Size might be. In this case, if n_arg happens to be negative, converting it to size_t will not work well.
Perhaps something like this:
(It doesn't compile but you get the idea)
Yes, it solves some of the problems, but not all.
How do we separate
enum E1 { a = -42 };
from
enum E2 { a = UINT_MAX};
??
Or, even worse
struct T1
{
operator int();
};
from
struct T2
{
operator unsigned long();
};
??
I don't know? Perhaps this really is a defect in the standard?
>
enum MyEnum { a,b,c,d,e,f };
template<class T, bool is_signed = ((T)-1 < 0)>
void Func(T arg);
This will not work for the structs, that are convertible *to* an
integral type, but not *from*.
Bo Persson
>
template<class T>
void Func<T,true>(T arg)
{
long i = arg;
}
template<class T>
void Func<T,false>(T arg)
{
long unsigned i = arg;
}
int main()
{
MyEnum obj;
Func(obj);
}
--
Frederick Gotham
"Kai-Uwe Bux" <jk********@gmx.netskrev i meddelandet
news:ec**********@murdoch.acc.Virginia.EDU...
Bo Persson wrote:
>> "Fraser Ross" <fraserATmembers.v21.co.ukskrev i meddelandet news:11***********@sp6iad.superfeed.net...
>>>A suitable implementation is easy enough to make. It surprises me how much library code uses pre increment and decrement operators. They can be less efficient.
Fraser.
I don't think it is obvious how to select a proper integral type for n, when you don't know what type Size might be. In this case, if n_arg happens to be negative, converting it to size_t will not work well.
If Size happens to be a class type with a user defined convertion operator, how do we know what type(s) it will convert to? Signed, or unsigned?
Who says that it is necessary to make a guess as to whether Size
converts to
signed or unsigned? What about:
template < typename OutIter, typename Size, typename T >
void fill_n ( OutIter first, Size n, const T & value ) {
for ( std::size_t i = 0; i < n; ++i ) {
*first = value;
++first;
}
}
Yes, we are getting closer. :-)
My compiler would complain about a signed/unsigned comparison when
Size really is signed.
One could use specialization tricks to save the local variable when
Size is
an arithmetic type.
Perhaps we could have an overload
template < typename OutIter, typename T >
void fill_n ( OutIter first, std::size_t n, const T & value );
to catch the cases where std::size_t is the proper type?
That would leave the signed case for the original version. Wouldn't
that work?
Bo Persson
Bo Persson wrote:
>
"Kai-Uwe Bux" <jk********@gmx.netskrev i meddelandet
news:ec**********@murdoch.acc.Virginia.EDU...
>Bo Persson wrote:
>>> "Fraser Ross" <fraserATmembers.v21.co.ukskrev i meddelandet news:11***********@sp6iad.superfeed.net... A suitable implementation is easy enough to make. It surprises me how much library code uses pre increment and decrement operators. They can be less efficient.
Fraser.
I don't think it is obvious how to select a proper integral type for n, when you don't know what type Size might be. In this case, if n_arg happens to be negative, converting it to size_t will not work well.
If Size happens to be a class type with a user defined convertion operator, how do we know what type(s) it will convert to? Signed, or unsigned?
Who says that it is necessary to make a guess as to whether Size converts to signed or unsigned? What about:
template < typename OutIter, typename Size, typename T > void fill_n ( OutIter first, Size n, const T & value ) { for ( std::size_t i = 0; i < n; ++i ) { *first = value; ++first; } }
Yes, we are getting closer. :-)
My compiler would complain about a signed/unsigned comparison when
Size really is signed.
It should not. Such comparison is handled gracefully by promotion rules. I
think, the code is required to compile.
>One could use specialization tricks to save the local variable when Size is an arithmetic type.
Perhaps we could have an overload
template < typename OutIter, typename T >
void fill_n ( OutIter first, std::size_t n, const T & value );
to catch the cases where std::size_t is the proper type?
That would leave the signed case for the original version. Wouldn't
that work?
I would add overloads for all integral types.
Best
Kai-Uwe Bux
"Kai-Uwe Bux" <jk********@gmx.netskrev i meddelandet
news:ec**********@murdoch.acc.Virginia.EDU...
Bo Persson wrote:
>> "Kai-Uwe Bux" <jk********@gmx.netskrev i meddelandet news:ec**********@murdoch.acc.Virginia.EDU...
>>Bo Persson wrote:
"Fraser Ross" <fraserATmembers.v21.co.ukskrev i meddelandet news:11***********@sp6iad.superfeed.net... >A suitable implementation is easy enough to make. It surprises >me >how much library code uses pre increment and decrement operators. They can be less efficient. > Fraser.
I don't think it is obvious how to select a proper integral type for n, when you don't know what type Size might be. In this case, if n_arg happens to be negative, converting it to size_t will not work well.
If Size happens to be a class type with a user defined convertion operator, how do we know what type(s) it will convert to? Signed, or unsigned?
Who says that it is necessary to make a guess as to whether Size converts to signed or unsigned? What about:
template < typename OutIter, typename Size, typename T > void fill_n ( OutIter first, Size n, const T & value ) { for ( std::size_t i = 0; i < n; ++i ) { *first = value; ++first; } } Yes, we are getting closer. :-)
My compiler would complain about a signed/unsigned comparison when Size really is signed.
It should not. Such comparison is handled gracefully by promotion
rules. I
think, the code is required to compile.
It does with a warning, but the result is incorrect. :-(
If Size is ptrdiff_t for example, and n is negative, comparing to a
size_t doesn't work.
We are on the right track though, and I think this one could work:
template < typename OutIter, typename Size, typename T >
void fill_n ( OutIter first, Size n, const T & value ) {
if (0 < n) // n must be positive
{
for ( std::size_t count = n; 0 < count; --count ) {
*first = value;
++first;
}
}
}
If we sort out the possibly negative n first, the remaining values
must be convertible to size_t (assuming size_t is the largest unsigned
type :-).
Bo Persson
Bo Persson posted:
My compiler would complain about a signed/unsigned comparison when
Size really is signed.
Simply cast one of them -- I regularly use casts to suppress compiler
warnings, e.g.:
for(size_t i = MAX - 1; i != (size_t)-1; --i)
--
Frederick Gotham
"Frederick Gotham" <fg*******@SPAM.comskrev i meddelandet
news:Ce*******************@news.indigo.ie...
Bo Persson posted:
>My compiler would complain about a signed/unsigned comparison when Size really is signed.
Simply cast one of them -- I regularly use casts to suppress
compiler
warnings, e.g.:
for(size_t i = MAX - 1; i != (size_t)-1; --i)
That just works sometimes.
If the signed value really is negative, it doesn't help.
int x = -5;
unsigned y = UINT_MAX;
if (x < y)
...
Bo Persson
Bo Persson wrote:
"Frederick Gotham" <fg*******@SPAM.comskrev i meddelandet
news:Ce*******************@news.indigo.ie...
>Bo Persson posted:
>>My compiler would complain about a signed/unsigned comparison when Size really is signed.
Simply cast one of them -- I regularly use casts to suppress compiler warnings, e.g.:
for(size_t i = MAX - 1; i != (size_t)-1; --i)
That just works sometimes.
If the signed value really is negative, it doesn't help.
int x = -5;
unsigned y = UINT_MAX;
if (x < y)
...
What is the expected result? Since -5 converted to unsigned is the
same as unsigned((UINT_MAX + 1) - 5), it's less than UINT_MAX. If
both of them are promoted to 'long', -5 is still less than UINT_MAX
which is positive. If they are promoted to unsigned long, see the
unsigned thing above.
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Victor Bazarov wrote:
[..] Since -5 converted to unsigned is the
same as unsigned((UINT_MAX + 1) - 5)[..]
Now that I'm thinking about it again, it's probably implementation-
defined and not that simple... Sounded plausible, didn't it? :-)
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Bo Persson wrote:
>
"Kai-Uwe Bux" <jk********@gmx.netskrev i meddelandet
news:ec**********@murdoch.acc.Virginia.EDU...
>Bo Persson wrote:
>>> "Kai-Uwe Bux" <jk********@gmx.netskrev i meddelandet news:ec**********@murdoch.acc.Virginia.EDU... Bo Persson wrote:
> "Fraser Ross" <fraserATmembers.v21.co.ukskrev i meddelandet news:11***********@sp6iad.superfeed.net... >>A suitable implementation is easy enough to make. It surprises >>me >>how >much library code uses pre increment and decrement operators. >They >can >be less efficient. >> >Fraser. > > I don't think it is obvious how to select a proper integral type for n, when you don't know what type Size might be. In this case, if n_arg happens to be negative, converting it to size_t will not work well. > If Size happens to be a class type with a user defined convertion operator, how do we know what type(s) it will convert to? Signed, or unsigned?
Who says that it is necessary to make a guess as to whether Size converts to signed or unsigned? What about:
template < typename OutIter, typename Size, typename T > void fill_n ( OutIter first, Size n, const T & value ) { for ( std::size_t i = 0; i < n; ++i ) { *first = value; ++first; } }
Yes, we are getting closer. :-)
My compiler would complain about a signed/unsigned comparison when Size really is signed.
It should not. Such comparison is handled gracefully by promotion rules. I think, the code is required to compile.
It does with a warning, but the result is incorrect. :-(
If Size is ptrdiff_t for example, and n is negative, comparing to a
size_t doesn't work.
You'r right. My bad.
We are on the right track though, and I think this one could work:
template < typename OutIter, typename Size, typename T >
void fill_n ( OutIter first, Size n, const T & value ) {
if (0 < n) // n must be positive
{
for ( std::size_t count = n; 0 < count; --count ) {
*first = value;
++first;
}
}
}
If we sort out the possibly negative n first, the remaining values
must be convertible to size_t (assuming size_t is the largest unsigned
type :-).
Looks good. Maybe, I would do
template < typename OutIter, typename Size, typename T >
void fill_n ( OutIter first, Size n, const T & value ) {
if (0 <= n) // n must not be negative
{
for ( std::size_t count = n; 0 < count; --count ) {
*first = value;
++first;
}
}
}
to make it easier for the compiler to optimize the if-statement away if Size
is an unsigned type.
Best
Kai-Uwe Bux
template <class OutputIterator, class Size, class T>
void fill_n (OutputIterator first, Size n, const T& value) {
if (1 <= n) {
size_t m= n;
do {
--m;
*first= value;
++first;
}
while (1 <= m);
}
};
I had roughly the same code. I would have written almost the same as
you after noticing that a for statement can be used. The optimisation
though I wouldn't have known about.
Fraser.
template < typename OutIter, typename Size, typename T >
void fill_n ( OutIter first, Size n, const T & value ) {
if (0 <= n) // n must not be negative
{
for ( std::size_t count = n; 0 < count; --count ) {
*first = value;
++first;
}
}
}
to make it easier for the compiler to optimize the if-statement away
if Size
is an unsigned type.
Posted Via Usenet.com Premium Usenet Newsgroup Services
----------------------------------------------------------
** SPEED ** RETENTION ** COMPLETION ** ANONYMITY **
---------------------------------------------------------- http://www.usenet.com This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: Anon Email |
last post by:
Hi people,
I'm learning about header files in C++. The following is code from
Bartosz Milewski:
// Code
const int maxStack = 16;
class IStack
|
by: karan.shashi |
last post by:
Hey all,
I was asked this question in an interview recently:
Suppose you have the method signature
bool MyPairSum(int array, int sum)
the array has all unique values (no repeats), your...
|
by: DolphinDB |
last post by:
Tired of spending countless mintues downsampling your data? Look no further!
In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
|
by: isladogs |
last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM).
In this month's session, we are pleased to welcome back...
|
by: Vimpel783 |
last post by:
Hello!
Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
|
by: jfyes |
last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
|
by: ArrayDB |
last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
|
by: PapaRatzi |
last post by:
Hello,
I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
|
by: CloudSolutions |
last post by:
Introduction:
For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
|
by: af34tf |
last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
|
by: isladogs |
last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM).
In this session, we are pleased to welcome former...
| |