
AMDG On 12/01/2012 07:20 AM, Peter Sommerlad wrote:
Hi Jeff
On 01.12.2012, at 02:53, Jeffrey Lee Hellrung, Jr. wrote:
And a default initialized scalar type, isn't.
"isn't"...what, exactly?
it isn't initialized with a defined value.
struct X{ X(){} unsigned x; }; void foo(){ X y; // -> y.x has an uninitialized value AFAIK if it is local } that is the situation we run into with the default constructed counting_iterator<unsigned>()
IMO, this is a good thing. Any use of a default constructed counting_iterator is probably wrong, no matter what (arbitrary) value is chosen. As such, it's better to leave it uninitialized, so these errors can be caught by tools like valgrind.
I'm not opposed to giving defined behavior to a default constructed counting_iterator< [integral type] >, I'm just not sure what that defined behavior should be. Maybe I'm over-analyzing it...
I still believe the most simple change I suggested is enough (at least it would cover my situation well enoughi).
Your use case is very error prone. It only works because you started the iteration at 1, not 0.
Those input iterators where a default constructed one is the end iterator is IMHO more of an exception, because it is a special case for the stream iterators.
Any other iterator gives undefined behavior when it's default constructed. I don't see why counting_iterator should be different.
Your idea with std::numberic_limits< Iterator >::max() requires a much more complex solution with template meta programming, i.e., enable_if<is_arithmetic<Iterator>> or similar. And it won't provide the default value of Iterator, which is zero in the case of the built-in arithmetic types, i.e., unsigned().
What do you think?
In Christ, Steven Watanabe