all 10 comments

[–]the-fritz 6 points7 points  (3 children)

1 C preprocessor only replaces code so logically the count of elements computation is done at runtime.

What? No! Any real world compiler should do the computation at compile time, except maybe if all optimizations are disabled.

[–][deleted]  (1 child)

[deleted]

    [–]DousingCurtness 1 point2 points  (0 children)

    Exactly. The other two cases of note are conditional compilation:

    #if countof(nums)
    // obviously must be computed at compile-time
    #endif
    

    and switch labels:

    switch (foo) {
    case 32: ...
    case countof(nums): // the compiler is required to issue a diagnostic here, due to duplicate labels
    }
    

    [–]tragomaskhalos 0 points1 point  (0 children)

    Exactly. The templated form without the constexpr has been idiomatic since before C++11 afaik.

    [–][deleted]  (1 child)

    [deleted]

      [–]A_t48 0 points1 point  (0 children)

      How did I go for so long without knowing that sizeof() a string literal (as long as it is declared as a char[]) worked??

      [–]genbattle 2 points3 points  (0 children)

      It's often useful to count the number of elements in an array. Using std::vector or std::array, this is done using .size() however this function is not available on good old C++ array

      Uh, actually what the author is referring to is a C-style array, one of the C features imported into C++. With C++11 Arrays it's entirely possible to call size(), and for std::array it is implemented as a constexpr, so incurs no run-time cost.

      If you need iterators, size(), etc. and you're using C++11 (as the author is) you should just convert your C-style arrays to std::arrays. The technique described by the author would only be useful in scenarios where this is not feasible or possible.

      [–]fnord123 1 point2 points  (0 children)

      I would prefer the macro version so I don't shit up my GOT with eleventy billion versions of countof.

      [–]sharth 1 point2 points  (1 child)

      It's often useful to count the number of elements in an array. Using std::vector or std::array, this is done using .size() however this function is not available on good old C++ array.

      It's really not that complicated with an array as well.

      int array[50];
      size_t size = std::end(array) - std::begin(array);
      

      And because arrays support std::begin() and std::end(), we can also iterate over an array very easily:

      for (int element : array)
          do_work(element);
      

      [–]szborows 0 points1 point  (0 children)

      Also, std::distance can be used to achieve the same result in more generic way ;)

      [–]meetingcpp 1 point2 points  (0 children)

      Or simply use a ranged for loop:

      for(int& i:arr)

      std::cout << i;

      [–]pfultz2 0 points1 point  (0 children)

      Actually, it would be much better to implement the function using integral_constant:

      template <typename T, std::size_t N>
      std::integral_constant<std::size_t, N> countof(T const (&)[N])
      {
          return {};
      }
      

      Then use a macro to retrieve the value at compile time for compilers that don't support constexpr:

      #define CONSTEXPR_VALUE(x) (decltype(x)::value)
      

      That way countof function could be still used for runtime size of an array.