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<ptr_arr_using, ptr_arr_typedef>); // pointer to array
static_assert(std::is_same_v<arr_ptr_using, arr_ptr_typedef>); // array of pointers
static_assert(!std::is_same_v<arr_ptr_using, ptr_arr_using>); // arr_ptr != ptr_arr
Important: () parentheses control operator precedence in declaration
What hinted me to this
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 hint: int(*)[]
Why it is so?
The dispatch order of operators in declaration is the same as in C++ Operator Precedence and Associativity table: https://en.cppreference.com/w/cpp/language/operator_precedence
TL;DR
[] - precede first and associated Left to right ->
& * * const/volatile - precede after and associated Right to left <-
() determine the highest precedence (for operators inside)
arraysto another question aboutfunctions. They might seem similar due to commonpointerbase in both topics. But the solution to each question has different: syntax and meaning. Also while initially searching for solution to this (array) question - no suitable answers were found on the net (not just stackoverflow), including that duplicate question (did not even appeared in my search results), which still would not answer my question back then, and not answering it right now.