Ich habe diese Klassen:
#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;
}
Ist beim Kompilieren a_m
nicht standardmäßig konstruierbar, a
ist es aber .
Beim Wechsel C
zu:
struct C {
int i;
};
alles ist gut.
Getestet mit Clang 9.0.0.
C() {}
funktioniert es auch.static_assert
InA
schlägt fehl, aber wenn Sie stattdessen standardmäßig einT
Inside von erstellenA
(z. B. ein MitgliedT t;
dort platzieren), funktioniert alles einwandfrei. Eine Inkonsistenz zwischen dem, was dasconst int x;
ist ohne Initialisierer ungültig, allein aufgrund desconst
und des Initialisierungsverhaltens von eingebauten Typen und einigen Geschichte)Antworten:
Dies wird sowohl durch den Text des Standards als auch durch mehrere wichtige Implementierungen, wie in den Kommentaren angegeben, nicht zugelassen, jedoch aus völlig unabhängigen Gründen.
Erstens der Grund "nach dem Buch": Der Punkt der Instanziierung von
A<C>
liegt nach dem Standard unmittelbar vor der Definition vonB
und der Punkt der Instanziierung vonstd::is_default_constructible<C>
liegt unmittelbar davor:Da
C
dies zu diesem Zeitpunkt eindeutig unvollständig ist, ist das Verhalten der Instanziierungstd::is_default_constructible<C>
undefiniert. Siehe jedoch Kernproblem 287 , das diese Regel ändern würde.In Wirklichkeit hat dies mit dem NSDMI zu tun.
= 0
könnte sich also im Prinzip auf Dinge beziehen, dieB
noch nicht deklariert sind, sodass die Implementierung nicht wirklich versuchen kann, sie zu analysieren, bis sie fertig istB
.C
kein Konstruktor deklariert ist.A<C>
, dies fürC
unvollständig.Dieser gesamte Bereich, der sich mit Regionen mit verzögerter Analyse befasst, ist stark unterbestimmt, mit der damit einhergehenden Divergenz bei der Umsetzung. Es kann eine Weile dauern, bis es aufgeräumt wird.
quelle
Undefiniertes Verhalten ist es:
quelle
C
ist vollständig, aberB
nicht. UndB::C
hängt indirekt davon abB
.C
es eine Standardkonstruktorvorlage mit einer seltsamen SFINAE gibt, die Antworten ändern kann, wennB
sie anders ausgeführt wird, hängt das Merkmal davon ab.