I have a C++ concept for checking that an array of objects can be dynamically allocated:
template< class T, int N >
concept heap_constructible = requires() {
delete[] new T[N];
};
And I found accidently that compilers diverge in its evaluation in case of zero-size arrays N=0
and inaccessible (e.g. private:
) constructor:
class A {
A();
};
static_assert( !heap_constructible<A, 5> ); // OK everywhere
static_assert( heap_constructible<A, 0> ); // OK in GCC only
Only GCC seems to allow zero-size allocation of A
-objects. Clang prints the error:
calling a private constructor of class 'A'
In case of slight modification of the concept:
template< class T, int N >
concept heap_constructible1 = requires() {
delete[] new T[N]{}; // note additional empty braced list
};
Clang accepts it as well:
static_assert( heap_constructible1<A, 0> ); // OK in GCC and Clang
but not MSVC, which evaluates both heap_constructible<A, 0>
and heap_constructible1<A, 0>
to false
. Online demo: https://gcc.godbolt.org/z/nYr88avM4
Which compiler is right here?
new char[0]
is valid standard C++ whilechar arr[0];
is not. – Pappanonew char[0]
does not declare a zero-length array. But you're right that my previous comment is not directly relevant to the question. – Datchaauto ptr = new A[0]{};
makes clang ok with it too, like OP observed. – Mikkel{}
makes it ok but leaving it out is not, gcc seems to be correct like StoryTeller said. – MikkelN
innew T[N]
is not a constant-expression or some other context in which a constant expression is required. Furthermore, I don't see any special casing for when the expression in the brackets is a (converted) constant expression in [expr.new]. Therefore, I don't see how the necessity for overload resolution or accessibility checks can depend on the actual value of the expressionN
. – NonstriatedN
needs to be a constant expression innew T[N]
- or I may have missed it. Whom are you addressing? – Mikkel