Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>As a rule, in C and C++ you should never use an unsigned type such as <code>size_t</code> to restrict the domain. That's because (1) these languages provide no range checking, and (2) they do provide unreasonable implicit promotions. No range checking means (1) no advantage, and unreasonable implicit promotions means (2) very undesirable disadvantages, so it's plain stupid thing to do: no advantage, very undesirable disadvantages.</p> <p>However, the standard libraries for these languages do that. They do it for <em>historical reasons</em> only, caught irreversibly in early decisions which at one time made sense. This has both extremely silly consequences such as C99 requiring 17 (!) bits for <code>ptrdiff_t</code>, and it has the aforementioned extremely undesirable consequences such as using inordinately much time on hunting down bugs resulting from implicit promotions (etc.). For example, in C++ you are practically guaranteed that <code>std::string( "bah!" ).length() &lt; -5</code> &ndash; which can easily trip you up and anyway is as silly as it is possible to design.</p> <p>Now, you can't infuse new member functions in <code>std::vector</code>, but you can add a freestanding function. A good name is <code>countOf</code>. Template it so that it can be applied to just about anything (raw arrays, vectors, etc.).</p> <p>The triad of functions <code>startOf</code>, <code>endOf</code> and <code>countOf</code> were, as far as I know, first identified by Dietmar Kuehl. C++0x will have <code>std::begin</code> and <code>std::end</code>, but AFAIK no corresponding <code>std::size</code>. In the meantime you can just define this support, which allows you to treat any kinds of container plus raw arrays the same.</p> <p>An example implementation &amp; further discussion is provided at <a href="http://alfps.wordpress.com/2010/05/10/how-to-avoid-disastrous-integer-wrap-around/" rel="nofollow">my blog</a>.</p> <hr/> <p><strong>EDIT</strong> Adding some code, because it's requested in the comments.</p> <p>Detection of suitable iterator type:</p> <pre><code>template&lt; typename Type &gt; struct It { typedef typename Type::iterator T; }; template&lt; typename Type &gt; struct It&lt; Type const &gt; { typedef typename Type::const_iterator T; }; template&lt; typename ElemType, Size N &gt; struct It&lt; ElemType[N] &gt; { typedef ElemType* T; }; </code></pre> <p>And the <code>countOf</code>, <code>startOf</code> and <code>endOf</code> functions, using that deduced iterator type:</p> <pre><code>template&lt; typename T &gt; inline Size countOf( T const&amp; c ) { return static_cast&lt;Size&gt;( c.size() ); } template&lt; typename T, Size N &gt; inline Size countOf( T (&amp;)[N] ) { return N; } template&lt; typename T &gt; inline typename It&lt;T&gt;::T startOf( T&amp; c ) { return c.begin(); } template&lt; typename T, Size N &gt; inline T* startOf( T (&amp;a)[N] ) { return a; } template&lt; typename T &gt; inline typename It&lt;T&gt;::T endOf( T&amp; c ) { return c.end(); } template&lt; typename T, Size N &gt; inline T* endOf( T (&amp;a)[N] ) { return a + N; } </code></pre> <p>where <code>Size</code> is a typedef for <code>ptrdiff_t</code>.</p> <p>Note: in 64-bit Windows <code>int</code> (and even <code>long</code>) is 32-bit. Hence, <code>int</code> is in general not sufficient for a really large array. <code>ptrdiff_t</code> is guaranteed to be able to represent the difference between any two pointers, when that difference is well-defined.</p> <hr> <p>Cheers &amp; hth.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload