When the compiler evaluates ValueType() in Get, I would have expected it to become (int*)(), but since this is invalid, is it treated differently?
A C++ template, while being very similar to a macro, does not perform a literal replacement. ValueType remains an actual type within the scope of the template. So yes, return ValueType() would be treated differently from (int*)(), more like using ValueType = int*; return ValueType();
As to why using ValueType = int*; ValueType(); works when (int*)() doesn't:
In C++, an expression of the form T() (when T is a type) is value-initialization syntax which creates a nameless object of type T.
During value-initialization, non-class types are zero-initialized.
The problem is (int*)() does not have the form T(), but (T)(). (int*)() is parsed as a cast to int*, but then it's missing the value to cast. Which is exactly what the compiler says in the error:
<source>:2:27: error: expected expression
int* IntPtr2 = (int*)();
^
For the same reason using T = int; int x = (T)(); also won't compile.
Similarly int* IntPtr3 = (int*){}; is also invalid C++ (GCC compiles it, but e.g. MSVC won't).
Some possible workarounds:
typedef the pointer to some type, then you'll be able to use the T() form normally:
using T = int*;
T ptr = T();
Use copy-list-initialization syntax:
int* ptr = {};
Use direct-list-initialization syntax:
int* ptr{};
Note that the direct-initialization form int* ptr(); is also unusable as it is subject to most vexing parse.