Istnieje już duża liczba pytań na temat unique_ptr i niekompletnego typu na SO, ale żaden nie może dać mi pojęcia, dlaczego poniższe nie ma praca:C++ 11: unique_ptr narzeka na niekompletny typ, ale nie kiedy go zawijam
// error: ... std::pair<...>::second has incomplete type
template<typename K, typename T> struct Impl {
typedef typename std::unordered_map<K,Impl<K,T>>::iterator iter_type;
std::unique_ptr<iter_type> ptr;
Impl() : ptr(new iter_type()) {}
};
int main() { Impl<int,int>(); return 0; }
natomiast następujące robi:
template<typename K, typename T> struct Impl {
struct Wrapper {
typedef typename std::unordered_map<K,Impl<K,T>>::iterator iter_type;
iter_type iter;
};
std::unique_ptr<Wrapper> ptr;
Impl() : ptr(new Wrapper()) {}
};
int main() { Impl<int,int>(); return 0; }
nie widzę gdzie różnica techniczna jest: Jeśli std::pair<...>::second
(czyli Impl<K,T>
) był niekompletny do Impl
w pierwszym przykładzie, to powinien być niekompletny t o Wrapper
również w drugim. Ponadto, , gdy wystarczy zawinąć unique_ptr
w strukturze, dlaczego istnieje ograniczenie dla pierwszego przypadku?
UPDATE:
Po odpowiedź Dietmar Kuhl za, myślę, że problem można sprowadzić do następujących:
template<typename K, typename T> struct Impl {
typename std::unordered_map<K,Impl<K,T>>::iterator ptr;
};
vs
template<typename K, typename T> struct Impl {
struct Wrapper {
typename std::unordered_map<K,Impl<K,T>>::iterator iter;
};
Wrapper *ptr;
};
Czy masz na myśli różnicę polegającą na tym, że konstruktor 'Wrapper' nie został skompilowany przed zaimplementowaniem ** klasy' Impl' ** w pełni implementowanej? Tak więc Wrapper tworzy sztucznie całą konstrukcję dwuetapowego procesu, gdy efektywnie kolejność kompilacji może być dokładnie taka sama? –
@JoSo: Członkowie szablonów klas są tworzone instancjami, gdy są używane. 'Wrapper' jest członkiem szablonu klasy i jest używany tylko w definicji konstruktora. 'Typedef' tak naprawdę nie jest członkiem i zdefiniowanie szablonu klasy' Impl' jest instancją. Tak, tak, czyniąc go procesem dwustopniowym, unikaj problemu typu, który jednak nie został zdefiniowany. –
Nie powinno być sposobu, aby powiedzieć kompilatorowi "tak, ten typ naprawdę istnieje!" ?. To znaczy, mogę też powiedzieć 'struct NewType; NewType * ptr; 'wewnątrz klasy bez definiowania NewType i działa! Czy jest to tylko słabość specyfikacji/implementacji, czy też istnieją głębsze przyczyny? –