2

Given the following function:

template<class T>
void foo(T* ar)
{
    std::cout << sizeof(ar) / sizeof(ar[0]) << std::endl;
    for (int i = 0; i < 6; i++)
        std::cout << ar[i] << " ";
}

And following array:

int ar[] = { 5, 1, 6, 8, 9, 3 };
foo(ar);

I expected the program to print '6' and then the contents of the array. But for some reason, sizeof(ar) / sizeof(ar[0]) evaluates to 1 (since both sizeof(ar) and sizeof(ar[0]) evaluate to '4'), but the print works fine (meaning passed array does contain all 6 elements).

This only happens to arrays passed to functions (I tried evaluating length in main(), where array was declared and it worked fine). How can I get the length of an array inside a function?

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Ach113
  • 1,775
  • 3
  • 18
  • 40

1 Answers1

3

Just declare the parameter as having a referenced type.

For example

template<class T>
void foo( const T &ar )
{
    size_t n = sizeof(ar) / sizeof(ar[0]);
    std::cout << n << std::endl;
    for (int i = 0; i < n; i++)
        std::cout << ar[i] << " ";
}

Or you may use the following declaration

template<class T, size_t N>
void foo( const T ( &ar )[N] )
{
    std::cout << N << std::endl;
    for (int i = 0; i < N; i++)
        std::cout << ar[i] << " ";
}

Otherwise the function deals with a pointer. In this case you need specify a second parameter that denotes the length of the array like

template<class T>
void foo( const T* ar, size_t n )
{
    std::cout << n << std::endl;
    for (int i = 0; i < n; i++)
        std::cout << ar[i] << " ";
}

As the passed array is not being changed in the function then the corresponding parameter should have the qualifier const.

Pay attention to that in the C++ 17 Standard there is introduced standard function std::size declared in the header <iterator> that can be used instead of the expression sizeof(ar) / sizeof(ar[0])

So you could write for example in the first shown function

size_t n = std::size(ar)`;
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • I think I will go with the first one, `void foo( const T &ar )`, but in this case type T becomes `array`. Is there any way to get the type of the element of that array? – Ach113 Apr 21 '20 at 08:58
  • @Ach113 You can include the header and use something like typename std::remove_extent_t> x; – Vlad from Moscow Apr 21 '20 at 09:07
  • @Ach113 You can this long record make shorter by using an alias declaration. For example using Type = typename std::remove_extent_t>; Type x = 10; – Vlad from Moscow Apr 21 '20 at 09:10
  • thing is, I want to create an object of that type `SomeObject`. I need to pass a datatype like `int` to it. But if T becomes an array, what could I do in this case? – Ach113 Apr 21 '20 at 09:12
  • 1
    @Ach113 You can declare the function like template void foo( const T &ar, typename std::remove_extent_t x ); – Vlad from Moscow Apr 21 '20 at 09:23
  • I think the last piece of code should have constexpr : `constexpr size_t N = std::size(ar)`;` – Robert Andrzejuk Apr 23 '20 at 01:02