If we go to the draft C++ standard section 7.1.6.2
Simple type specifiers [dcl.type.simple] and see what the cases are, for decltype it starts out saying:
For an expression e, the type denoted by decltype(e) is defined as follows:
We see that in this case the expression is not an id-expression nor a class member access, which would give the result you expected(emphasis mine):
- if e is an unparenthesized id-expression or an unparenthesized class member access (5.2.5), decltype(e)
is the type of the entity named by e. If there is no such entity, or if e names a set of overloaded functions,
the program is ill-formed;
but the result is an lvalue:
- otherwise, if e is an lvalue, decltype(e) is T&, where T is the type of e;
which results in a reference.
As M.M point out std::remove_reference could be used to obtain the result you want:
std::remove_reference<decltype(Ptr[0])>::type Test = (int*)0;
As T.C. points out std::decay is also an option and is shorter:
std::decay<decltype(Ptr[0])>::type Test = (int*)0;