0

Tell me how to write a function that will take as an argument an array of any size, for example int elements, inside which it will be possible using the std::begin function to get a pointer to the first element of the array?

void func(array)
{
  auto arr_begin = std::begin(array);

  // ...
}

I found an example of a template function. It seems to be working correctly. Only it is not clear how this function learns that the argument was an array and how does it know the size of the array if it is not explicitly specified in the function? In fact, the parameter is written in the function as T& arr, i.e. T can be any type.

Why is the parameter not written like this: T(&arr)[] ?

I managed to write only a function that accepts an array of int elements but of a fixed size:

void func(const int (&arr)[5])  
{
  auto arr_begin = std::begin(arr); // OK

  // ...
}

How to write the same function but without specifying a fixed size? And is it possible to do this in principle?

iamnotevg
  • 17
  • 5
  • 1
    Instead of doing contortions to accept an array, do it the way the std algorithms do - pass two iterators. – Mark Ransom Nov 02 '22 at 18:31
  • 1
    arrays do not carry their run-time size with them - use a vector – Neil Butterworth Nov 02 '22 at 18:32
  • Mark Ransom, I understand that I'm not trying to make the best implementation, but this is purely for learning, I just want to figure out how everything works. – iamnotevg Nov 02 '22 at 18:41
  • 2
    The answer these days `std::span`. Or `std::array` and templating the function. Or `std::vector`. Basically stop using C-arrays unless you have a very good reason. – sweenish Nov 02 '22 at 18:43
  • Forget C-style arrays exist in the language. Use `std::array` or `std::vector` instead. – Jesper Juhl Nov 02 '22 at 18:48
  • "I just want to figure out how everything works" - Enjoy the journey. If you study hard and use C++ daily, we'll meet again in roughly 5+ years. It's a *complicated* language. – Jesper Juhl Nov 02 '22 at 18:51
  • @JesperJuhl And if I want to use the C language, then how do I write a function that takes an array of any size and returns a pointer to the first element? – iamnotevg Nov 02 '22 at 18:52
  • 1
    A array decays to a pointer to the first element. So a pointer to an array *is* a pointer to the first element. The trouble shows up when you want anything but the first element. Or when you want the size. Just don't use C arrays...! If you insist, then you'll have to also pass the array size as a separate parameter. – Jesper Juhl Nov 02 '22 at 18:55
  • 1
    You might want to consider writing the function to take *iterators* instead, then you can pass more things to your function. – Galik Nov 02 '22 at 19:02
  • A C style array does not know its own size and a pointer is just an address pointing to something in memory. If you need the size of a C style array you need to pass the size along - simple as that. You can't get the size of a container from a simple pointer. – Jesper Juhl Nov 02 '22 at 19:03

1 Answers1

3

You can't write a classic function for that; you need a template:

template<size_t N>
void func(const int (&arr)[N])
{
    auto arr_begin = std::begin(arr);
}
lorro
  • 10,687
  • 23
  • 36
  • Is this some kind of special type of template? I studied only the basics of templates and it was described that the template format is: template And I have not met the template format. How does it work? And how in my example does the template function know the size then if I didn't explicitly describe it in the template? – iamnotevg Nov 02 '22 at 18:38
  • 1
    @iamnotevg the even easier way, is to use a `std::array` as parameter – πάντα ῥεῖ Nov 02 '22 at 18:42
  • @πάνταῥεῖ, Yes, it's easier, but I just want to sort out my question. I understand that this is not worth using in practice – iamnotevg Nov 02 '22 at 18:44
  • 2
    @iamnotevg It is just a normal non-type template argument. It is exactly like your `const int (&arr)[5]` solution but the `5` is generalized as a template argument instead. The same way you specify a type template argument like `std::vector` you can pass a non-type value to a non-type template argument like `foo<5>(my_array);`. In this case, template argument deduction makes it unnecessary. The compiler is required to deduce `N` based on the argument provided to `func`. If `my_array` is a `int[5]` then `func(my_array)` will deduce `N` to be 5 based on the argument's type. – François Andrieux Nov 02 '22 at 18:51
  • 1
    This solution works as long as the array size is a compile-time constant. If you have a pointer to a dynamically allocated array or the array has already decayed to a pointer this solution will not work – François Andrieux Nov 02 '22 at 18:52
  • @πάνταῥεῖ Accepting `std::array<>` and passing c-style array means conversion, which is slow. – lorro Nov 02 '22 at 19:24
  • @FrançoisAndrieux `std::begin()` and `std::end()` wouldn't work for non-const sized array. – lorro Nov 02 '22 at 19:25