1
\$\begingroup\$

This code shows two ways to calculate size of array of any type. I would like to know, which should be preferred? Is there any advantage/disadvantage?

#include <iostream>

// First method
template<typename Arr>
std::size_t array_size_1(const Arr& arr)
{
  return sizeof(arr)/sizeof(arr[0]);
}
// Second method
template<typename T, std::size_t sz>
std::size_t array_size_2(const T (&arr)[sz])
{
  return sz;
}

int main() {
  int arr[] = {1,2,3,4,5};
  std::string sarr[] = {"abc", "def", "ghj"};
  std::cout << array_size_1(arr) << "\n";
  std::cout << array_size_2(sarr) << "\n";
  return 0;
}
\$\endgroup\$
  • 2
    \$\begingroup\$ How about std::size() \$\endgroup\$ – Martin York Feb 17 at 5:28
  • \$\begingroup\$ @MartinYork That's unfortunately C++17. \$\endgroup\$ – Deduplicator Feb 17 at 14:51
  • \$\begingroup\$ @Deduplicator Yea. But it tells you how to do it. \$\endgroup\$ – Martin York Feb 17 at 16:56
5
\$\begingroup\$

Both suffer (equal amounts) from the problem that when you call them, the compiler has to go instantiate a new function from the template. The code all ends up inlined after optimization, but it does make more work for the compiler than something like

#define NELEM(x) (sizeof(x) / sizeof (x)[0])

The benefit of array_size_2 is that if you try to call it as

int *p = nullptr;
std::vector<int> v;
size_t a = array_size_2(p);  // ERROR
size_t b = array_size_2(v);  // ERROR

the compiler will reject the call as ill-formed. Whereas if you do the same thing with array_size_1 or NELEM, you'll just get for example sizeof(int*) / sizeof(int) or sizeof(vector<int>) / sizeof(int), which isn't meaningful.

So array_size_2 saves you from accidentally writing something meaningless. Especially in cases like

int foo(int a[]) {
    return array_size_1(a);  // OOPS!
}

where int a[] is just syntactic sugar for int *a and there's no actual array in existence at all.

\$\endgroup\$
  • 1
    \$\begingroup\$ #define-ing NELEM is not best practice in C++ (as tags states C++). array_size_2 is a good way also to me. \$\endgroup\$ – fiorentinoing Feb 16 at 20:37
  • \$\begingroup\$ @fiorentinoing - Can you please explain why NELEM is not a good practice in c++ ? \$\endgroup\$ – bornfree Feb 17 at 3:41
  • \$\begingroup\$ my reference is Scott Meyers, Effective C++, Item 2: prefer consts, enums, and inlines to #defines. \$\endgroup\$ – fiorentinoing Feb 17 at 9:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.