0

I have been working thought the c++ standard library in order to better understand the usage and syntax of C++ templates. I have been able to understand the basics of templating, but some of the more complex syntax has left me needing further explanation. The following snippet is from the Microsoft xutility library.

template <class _Ty, size_t _Size>
_NODISCARD constexpr _Ty* begin(_Ty (&_Array)[_Size]) noexcept {
    return _Array;
}

I am confused about the function parameter _Ty (&_Array)[_Size]. Could somebody breakdown the syntax and explain it? I am most confused about the use of square brackets in a function parameter.

wallyk
  • 56,922
  • 16
  • 83
  • 148
Alec Matthews
  • 31
  • 1
  • 6
  • It's so you can pass in arrays like `int x[7]`, and it retains the size of the array. – ChrisMM Jul 14 '20 at 18:54
  • It's a reference to an array (of the given size and element type). – john Jul 14 '20 at 18:54
  • For historical reasons it's not possible for a function parameter to have an array type, but a reference to an array is allowed. – john Jul 14 '20 at 18:55
  • @john does this mean that function parameters can be passes as reference with their size taken into account? Say I wanted to create a function with the signature `add(int x[2], int y[2])` that sums two statically sized arrays. Does this signature only allow two position arrays as inputs? – Alec Matthews Jul 14 '20 at 18:58
  • Excuse me, if only references are allowed would the signature be `add(int (&x)[2], int (&y)[2])`? – Alec Matthews Jul 14 '20 at 19:01
  • Does this answer your question? https://stackoverflow.com/questions/5724171/passing-an-array-by-reference – 463035818_is_not_an_ai Jul 14 '20 at 19:02
  • Ah yes, thank you @idclev463035818! – Alec Matthews Jul 14 '20 at 19:03

1 Answers1

0

The code in question:

_Ty (&_Array)[_Size]

is a reference to a compile-time deduced array of type _Ty with size _Size.

Due to the way operator precedence works in C++, the actual types themselves are named somewhat strange to avoid syntactic ambiguities -- which is where the round brackets around the & and name exist.

All array types can be generalized to the form:

  1. T [N] -- an array of known size of T elements (the "value type")
  2. T (&) [N] -- a reference to an array (such as the one in (1))
  3. T (*) [N] -- a pointer to an array (such as the one in (1))

Where T may be possibly CV-qualified

Using this in a template just allows for the T and N types to be deduced.


Template type and non-type arguments can be deduced in function signatures when they are used for argument types, which is what this template is doing. If we clean it up some by removing the underscores, it would look something like:

template <class T, size_t N>
constexpr T* begin(T (&array)[N]) noexcept {
    return array;
}

This allows for both the type T and the array size N to be deduced, provided the type is an array. When being returned as a T*, it's relying on array-to-pointer decaying to produce a pointer.

Note: The _NODISCARD is likely just a compile-time macro evaluating to [[nodiscard]] when in C++17 mode, and either no attribute or a compiler-specific attribute like __attribute__((warn_unused_result)) in pre-C++17 mode.

Human-Compiler
  • 11,022
  • 1
  • 32
  • 59