The terms 'static type' and 'dynamic type' apply to expressions.
static type
type of an expression (3.9) resulting from analysis of the program without considering execution semantics
dynamic type
<glvalue> type of the most derived object (1.8) to which the glvalue denoted by a glvalue expression refers
Additionally, you can see that a dynamic type only differs from a static type when the static type can be derived from, which means a dynamic array type is always the same as the expression's static type.
So your question:
but how can one tell the type of the object created by the new expression at compile-time?
Objects have types, but they're not 'static' or 'dynamic' types absent an expression that refers to the object. Given an expression, the static type is always known at compile time. In the absence of derivation the dynamic type is the same as the static type.
But you're asking about objects' types independent of expressions. In the example you give you've asked for an object to be created but you don't specify the type of object you want to have created at compile time. You can look at it like this:
template<typename T>
T *create_array(size_t s) {
switch(s) {
case 1: return &(*new std::array<T, 1>)[0];
case 2: return &(*new std::array<T, 2>)[0];
// ...
}
}
There's little special or unique about this. Another possibility is:
struct B { virtual ~B() {}};
struct D : B {};
struct E : B {};
B *create() {
if (std::bernoulli_distribution(0.5)(std::default_random_engine())) {
return new D;
}
return new E;
}
Or:
void *create() {
if (std::bernoulli_distribution(0.5)(std::default_random_engine())) {
return reinterpret_cast<void*>(new int);
}
return reinterpret_cast<void*>(new float);
}
The only difference with new int[]
is that you can't see into its implementation to see it selecting between different types of objects to create.