1

I usually work in an environment where the highest supported version of modern C++ is C++14. I was experimenting with std::size from <iterator> in c++17 and came across the following issue / problem / lack of understanding on my part.

In the following code snippet the use of of size(a) in main works correctly but the usage in print refuses to compile stating that no matching function for call to 'size(int*&)' exists.

I know there are other, better ways of doing this but I would like to know why it works in the one context and not the other.

For what its worth I used the following online compiler and simply turned the -std=c++17 flag on.

#include <iostream>
#include <vector>
#include <iterator>

using namespace std;

void print(int a[])
{
   for(int i = 0; i < size(a); i++)
        cout << a[i] << endl;
}

int main() 
{
    int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

    cout << "Directly" << endl;
    for(int i = 0; i < size(a); i++)
        cout << a[i] << endl;

    cout << "Via function" << endl;
    print(a);

    return 0;
}
DuncanACoulter
  • 2,095
  • 2
  • 25
  • 38
  • 1
    That's because `a` in `print` is not an array, it's a pointer. There is no such thing in C++ (or C) as a *raw array parameter*. – john Aug 28 '19 at 09:25

1 Answers1

2

The first invocation of std::size uses this function template signature (#3 in the overload set here):

template <class T, std::size_t N>
constexpr std::size_t size(const T (&array)[N]) noexcept;

where the argument array has not decayed into a pointer. It's a raw array with the size encoded in its type. When you pass such an array to a function that accepts an int[] (or int*, that doesn't matter), the array decays into a pointer and the size is no longer part of the type. That's why std::size(a) can't compile. Concisely:

Why is <iterator>'s std::size not working with raw array parameters?

It is, but you're trying to use it with a pointer, not an array parameter.

lubgr
  • 37,368
  • 3
  • 66
  • 117
  • Also, `int[]` is actually a pointer to an array element, when it is a function parameter. – juanchopanza Aug 28 '19 at 09:21
  • So this is one of those cases where are arrays are basically like pointers except when they aren't? – DuncanACoulter Aug 28 '19 at 09:21
  • 1
    @DuncanACoulter Exactly. See also [here](https://stackoverflow.com/questions/33291624/why-do-arrays-in-c-decay-to-pointers) for example. – lubgr Aug 28 '19 at 09:22
  • @DuncanACoulter I find it best to first memorise that a function parameter may not be an array (reference to an array I possible though). Then that array parameters can be declared, but that declaration is adjusted to be a pointer and not an array at all. – eerorika Aug 28 '19 at 09:49
  • @eerorika I should have suspected it was a pointer-decay thing. As soon as this answer came in I realized what was going on. – DuncanACoulter Aug 28 '19 at 10:45