You absolutely cannot distinguish between pointers returned from new
and new[]
at compile-time. Not using templates, or standard type traits with compiler hooks, and not any other technique.
The reason for this should be obvious; if it's not, consider the following code: (things don't work like this; I'm just following your example.)
int * p = nullptr;
if (rand() % 2 == 0)
p = new int;
else
p = new int [42];
print_is_array (p); // Assume this does the detection and prints something.
How could you (and the compiler) know at compile time whether p
will be allocated using new
or new[]
?
Also, what you call "array" is more properly known as "vector" (not to be confused with std::vector
.) Arrays have some compile-time properties (like size) that run-time-allocated blocks of memory don't, even if you happen to construct multiple objects in them (e.g. with new[]
.)
And, passing an array of T
s (a real, proper, compile-time array) into a function that accepts T *
s will "decay" the type and lose the "arrayness". I'm referring here to the way you've defined your constructor, namely it taking a T *
.
If you are curious to see how to detect (proper) arrays at compile-time, take a look at the implementation of std::is_array<T>
template in the <type_traits>
header.
EDIT: By the way, this is what I mean when I say (proper) array:
int a [42];
not this:
int * p = new int [42];
These are two different types, but the first one can "decay" and be implicitly cast into the second type.