Re: 'npos' in string operations
- From: "Doug Harrison [MVP]" <dsh@xxxxxxxx>
- Date: Thu, 28 Apr 2005 22:42:26 -0500
On Fri, 29 Apr 2005 01:46:03 GMT, Gene Bushuyev wrote:
> "Doug Harrison [MVP]" <dsh@xxxxxxxx> wrote in message
> news:122d7mceraa0i$.dxac13mngnv8$.dlg@xxxxxxxxxxxxx
> ...
>>> It's related by its type to the allocator, not to the string class.
>>
>> Suppose there are classes X1, X2, X3, ... XN that define their own npos
>> analogues. Need I say more?
>
> Huh? I guess you need.
> ...
You stated that npos should be defined by the allocator class, despite the
fact it's a string concept that has nothing to do with allocators. There
are an infinite number of possible classes that might want to define
something similar to npos, which I captured with my X1, X2, X3, ... XN
example. By your reasoning, they should dump their npos analogues into
allocator. That does not compute.
>> My point is you're using the term in such a way that it loses its commonly
>> accepted meaning:
>>
>> http://www.clueless.com/jargon3.0.0/magic_number.html
>>
>
> Quote:
> "A number that encodes critical information used in an algorithm in some
> opaque way"
> - so what's wrong with that definition?
I guess something went wrong with your copy and paste job, so allow me to
restore the relevant parts that you omitted:
http://www.clueless.com/jargon3.0.0/magic_number.html
<q>
1. In source code, some non-obvious constant whose value is significant to
the operation of a program and that is inserted inconspicuously in-line
(hardcoded), rather than expanded in by a symbol set by a commented
`#define'. Magic numbers in this sense are bad style.
2. A number that encodes critical information used in an algorithm in some
opaque way. The classic examples of these are the numbers used in hash or
CRC functions, or the coefficients in a linear congruential generator for
pseudo-random numbers. This sense actually predates and was ancestral to
the more common sense 1.
</q>
You earlier said npos violates a "design rule":
<q>
Or better yet, npos shouldn't be there in
the first place, as it violates "avoid magic numbers" design rule.
</q>
The "design rule" you invoked refers to (1), and I explained why it doesn't
apply to npos in my first message. The "magic numbers" in (2) are essential
to the operation of the algorithms mentioned there, and for someone who
doesn't understand the algorithm that uses them, they certainly can seem
like magic. It doesn't make them any less necessary to the algorithm,
though, and they can't very well be "avoided". So again, there's a
difference.
> But I'm not going to argue about
> words. If you like calling it a special case constant instead of magic
> number, - it's fine with me.
It's just a plain ol' constant to me.
>>> Choosing the word (special) "constant"
>>> instead of "magic number" somehow supposed to change the meaning?
>>
>> Someone who sees "npos" in source code can easily look it up if he doesn't
>> know what it means. Someone who finds 284924073 has to pray there's a
>> comment nearby to explain it. There's a difference.
>
> That's not the point. The evil of npos is that it's just a single value from
> size_type set that has a *special meaning* Good design shouldn't contain any
> special constants that are treated differently than the other by the same
> functions.
> ...
As I also said, npos does not correspond to a valid position. In that
respect, it is like a past-the-end iterator or a NULL pointer. How is npos
"evil" while the latter two are (I guess) "good"?
>> Various string member functions accept and/or return positions.
> Designating
>> a singular value for position enables:
>>
>> 1. ctors and other functions specify npos as the value for a length
>> parameter to mean "the rest of the string" starting from some position
> pos.
>
> which 1) unnecessary, and 2) is better done through overloading, rather by
> defining default parameters
1. It can save you from determining string length yourself.
2. Where did I say anything about default parameters? Even if you overload
(pos) and (pos, length), the latter should still accept npos for length
because of (1). This can come up when you want just a fragment of the
string or the whole thing, so you use the (pos, length) overload, where
length is specified by (say) using the conditional operator.
>> 2. Functions such as find return size_type and need a way to encode "not
>> found".
>
> That's because of basic_string's terrible design. Have you seen any of the
> standard algorithms or other containers taking this approach. I can't find
> any. Because it's 1) unnecessary and 2) bad design. All string's *find*()
> functions should have returned iterators, which would be consistent and work
> well with the rest of the standard library containers and algorithms. In
> fact those *find*() functions shouldn't have been members in the first
> place, but rather more general (and more powerful) non-member algorithms, in
> fact most of std::*find* doing that work already exist. Now, if you get rid
> of the *find* duplicates and make the rest of string::*find* functions
> non-member functions returning iterators, nobody would even think about
> needing something as odd as basic_string::npos constant.
I'd agree the string interface is fat. I disagree that iterators are the
answer to everything. Often integer positions are more convenient to deal
with. Except for the find/compare member functions, which are defined only
on positions, the std::string class pretty much lets you choose the model
that suits the task at hand. And if you want to use string with generic
algorithms based on iterators, there's nothing stopping you, though the
cumbersome iterator-based find/compare functions in <algorithm> likely
aren't optimized for strings in the way the position-based find/compare
members likely are.
I have to wonder, given your disdain for the "magic" fixed value npos,
which has the type of a position but does not denote a legal position, how
do you feel about the "magic" non-fixed iterator returned by end(), which
has the type of an iterator but does not denote a legal position?
(That's a fair question. While end() has something to do with length, and
npos does not, iterator versions of the functions we're discussing would
return end(), or more generally y for the iterator range [x,y), to indicate
not-found in the same way the existing ones return npos. So in that
respect, there's no difference.)
--
Doug Harrison
Microsoft MVP - Visual C++
.
- Follow-Ups:
- Re: 'npos' in string operations
- From: Gene Bushuyev
- Re: 'npos' in string operations
- References:
- 'npos' in string operations
- From: Ian Semmel
- Re: 'npos' in string operations
- From: Gene Bushuyev
- Re: 'npos' in string operations
- From: Doug Harrison [MVP]
- Re: 'npos' in string operations
- From: Gene Bushuyev
- Re: 'npos' in string operations
- From: Doug Harrison [MVP]
- Re: 'npos' in string operations
- From: Gene Bushuyev
- 'npos' in string operations
- Prev by Date: Re: 'npos' in string operations
- Next by Date: Re: string to wstring
- Previous by thread: Re: 'npos' in string operations
- Next by thread: Re: 'npos' in string operations
- Index(es):