using ptr_arr_using = int(*)[]; // pointer to array <-- answer
typedef int (*ptr_arr_typedef)[]; // pointer to array
typedef int *arr_ptr_typedef []; // array of pointers
using arr_ptr_using = int*[]; // array of pointers
#include <type_traits>
static_assert( std::is_same_v<arr_ptr_using, arr_ptr_typedef>); // array of pointers
static_assert( std::is_same_v<ptr_arr_using, ptr_arr_typedef>); // pointer to array
static_assert(!std::is_same_v<arr_ptr_using, ptr_arr_using >); // arr_ptr != ptr_arr
An example "alias template" from https://en.cppreference.com/w/cpp/language/type_alias
template<class T> using ptr = T*;
using ptr_arr_using_template = ptr<int[]>; // then IDE showed `int(*)[]` hint
"The Clockwise/Spiral Rule" by David Anderson https://c-faq.com/decl/spiral.anderson.html
Will explain how to "parse complex declarations in your head".
This time C typedef
is slightly more readable vs C++ using
since it helps to locate the parsing entry point faster (by typename).
So ()
brackets control the order of things during the declaration process.
Overkill example:
const int *volatile(*const(*const volatile)[1])[2]
// cv*->[1]->с*->[2]->v*=>cT // T=int