I have those classes:
#include <type_traits>
template <typename T>
class A {
public:
static_assert(std::is_default_constructible_v<T>);
};
struct B {
struct C {
int i = 0;
};
A<C> a_m;
};
int main() {
A<B::C> a;
}
When compiling, a_m
is not default constructible but a
is.
When changing C
to:
struct C {
int i;
};
everything is fine.
Tested with Clang 9.0.0.
This is disallowed both by the text of the standard and by several major implementations as noted in the comments, but for completely unrelated reasons.
First, the "by the book" reason: the point of instantiation of A<C>
is, according to the standard, immediately before the definition of B
, and the point of instantiation of std::is_default_constructible<C>
is immediately before that:
For a class template specialization, [...] if the specialization is implicitly instantiated because it is referenced from within another template specialization, if the context from which the specialization is referenced depends on a template parameter, and if the specialization is not instantiated previous to the instantiation of the enclosing template, the point of instantiation is immediately before the point of instantiation of the enclosing template. Otherwise, the point of instantiation for such a specialization immediately precedes the namespace scope declaration or definition that refers to the specialization.
Since C
is clearly incomplete at that point, the behavior of instantiating std::is_default_constructible<C>
is undefined. However, see core issue 287, which would change this rule.
In reality, this has to do with the NSDMI.
= 0
could in principle refer to things in B
not yet declared, so the implementation can't really try to parse it until it has finished with B
.C
doesn't have a constructor declared.A<C>
, it thinks that C
is incomplete.This whole area dealing with delayed-parsed regions is woefully underspecified, with accompanying implementation divergence. It may take a while before it gets cleaned up.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With