Mam te zajęcia:
#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;
}
Podczas kompilacji a_m
nie jest domyślnie możliwy do zbudowania, ale a
jest.
Przy zmianie C
na:
struct C {
int i;
};
wszystko w porządku.
Testowane z Clang 9.0.0.
C() {}
tym też działa.static_assert
wA
nie, ale jeśli zamiast domyślnego skonstruowaćT
wewnątrzA
(np umieścić członT t;
tam), to działa wszystko jest w porządku. Niespójność między tym, co mówi ci cecha typu, a tym, co jest faktycznie możliwe ...const int x;
to samo zdanie na temat preferencji, jest niepoprawny bez inicjatora, wyłącznie ze względu naconst
zachowanie inicjalizacji wbudowanych typów i niektórych historia)Odpowiedzi:
Jest to niedozwolone zarówno w tekście standardu, jak i w kilku głównych implementacjach, jak zauważono w komentarzach, ale z zupełnie niezwiązanych powodów.
Po pierwsze, powód „z książki”: moment tworzenia instancji
A<C>
jest, zgodnie ze standardem, bezpośrednio przed definicjąB
, a moment tworzenia instancjistd::is_default_constructible<C>
znajduje się bezpośrednio przed tym:Ponieważ
C
w tym momencie jest on wyraźnie niekompletny, zachowanie tworzenia instancjistd::is_default_constructible<C>
jest niezdefiniowane. Patrz jednak główny problem 287 , który zmieniłby tę zasadę.W rzeczywistości ma to związek z NSDMI.
= 0
może to w zasadzie odnosić się do rzeczy, któreB
nie zostały jeszcze zadeklarowane, więc implementacja nie może tak naprawdę próbować go przeanalizować, dopóki się nie zakończyB
.C
nie ma deklarowanego konstruktora.A<C>
wydaje się, żeC
jest niekompletny.Cały ten obszar zajmujący się regionami z opóźnioną analizą jest żałośnie nieokreślony, a towarzyszy temu rozbieżność w zakresie wdrażania. Może minąć trochę czasu, zanim zostanie oczyszczony.
źródło
Niezdefiniowane zachowanie to:
źródło
C
jest kompletny, aleB
nie jest. IB::C
zależy pośrednio odB
.C
ma domyślny szablon konstruktora z jakimś dziwnym SFINAE, który może zmieniać odpowiedzi, jeśliB
zostanie wypełniony inaczej, to na pewno cecha zależy od niego.