There was a discussion on the C++ Core Guidelines what to use:
https://github.com/isocpp/CppCoreGuidelines/pull/1115
Herb Sutter wrote that gsl::index will be added (in the future maybe std::index), which will be defined as ptrdiff_t.
hsutter commented on 26 Dec 2017 •
(Thanks to many WG21 experts for their comments and feedback into this
note.)Add the following typedef to GSL
namespace gsl { using index = ptrdiff_t; }and recommend
gsl::indexfor all container indexes/subscripts/sizes.Rationale
The Guidelines recommend using a signed type for subscripts/indices.
See ES.100 through ES.107. C++ already uses signed integers for array
subscripts.We want to be able to teach people to write “new clean modern code”
that is simple, natural, warning-free at high warning levels, and
doesn’t make us write a “pitfall” footnote about simple code.If we don’t have a short adoptable word like
indexthat is competitive
withintandauto, people will still useintandautoand get their
bugs. For example, they will writefor(int i=0; i<v.size(); ++i)or
for(auto i=0; i<v.size(); ++i)which have 32-bit size bugs on widely
used platforms, andfor(auto i=v.size()-1; i>=0; ++i)which just
doesn’t work. I don’t think we can teachfor(ptrdiff_t i = ...with a
straight face, or that people would accept it.If we had a saturating arithmetic type, we might use that. Otherwise,
the best option isptrdiff_twhich has nearly all the advantages of a
saturating arithmetic unsigned type, except only thatptrdiff_tstill
makes the pervasive loop stylefor(ptrdiff_t i=0; i<v.size(); ++i)
emit signed/unsigned mismatches oni<v.size()(and similarly for
i!=v.size()) for today’s STL containers. (If a future STL changes its
size_type to be signed, even this last drawback goes away.)However, it would be hopeless (and embarrassing) to try to teach
people to routinely writefor (ptrdiff_t i = ... ; ... ; ...). (Even
the Guidelines currently use it in only one place, and that’s a “bad”
example that is unrelated to indexing`.)Therefore we should provide
gsl::index(which can later be proposed
for consideration asstd::index) as a typedef forptrdiff_t, so we can
hopefully (and not embarrassingly) teach people to routinely write for
(index i = ... ; ... ; ...).Why not just tell people to write
ptrdiff_t? Because we believe it
would be embarrassing to tell people that’s what you have to do in
C++, and even if we did people won’t do it. Writingptrdiff_tis too
ugly and unadoptable compared toautoandint. The point of adding the
nameindexis to make it as easy and attractive as possible to use a
correctly sized signed type.
Edit: More rationale from Herb Sutter
Is
ptrdiff_tbig enough? Yes. Standard containers are already required
to have no more elements than can be represented byptrdiff_t, because
subtracting two iterators must fit in a difference_type.But is
ptrdiff_treally big enough, if I have a built-in array ofchar
orbytethat is bigger than half the size of the memory address space
and so has more elements than can be represented in aptrdiff_t? Yes.
C++ already uses signed integers for array subscripts. So useindexas
the default option for the vast majority of uses including all
built-in arrays. (If you do encounter the extremely rare case of an
array, or array-like type, that is bigger than half the address space
and whose elements aresizeof(1), and you’re careful about avoiding
truncation issues, go ahead and use asize_tfor indexes into that
very special container only. Such beasts are very rare in practice,
and when they do arise often won’t be indexed directly by user code.
For example, they typically arise in a memory manager that takes over
system allocation and parcels out individual smaller allocations that
its users use, or in an MPEG or similar which provides its own
interface; in both cases thesize_tshould only be needed internally
within the memory manager or the MPEG class implementation.)