Jestem zdezorientowany tym, dlaczego mój kod nie generuje błędu invalid use of incomplete type
, podczas gdy cały odczyt, jaki zrobiłem na temat tego błędu, sugeruje, że powinien.
Pytanie wynika z tego błędu pokazuje się (zgodnie z oczekiwaniami) w ramach mojego kodu o podobnej strukturze, ale nie mogę odtworzyć go w małej przykład (patrz zrzeczenie na koniec pytanie).Nieprawidłowe użycie typu niekompletnego - dlaczego nie ma w tym przypadku błędu?
podsumowanie tego, co próbuję zrobić:
- Mam strukturę (
Tree
) i chcę, aby przypisać różne obiekty typu bazowegoFirst
do niego. - Konkretne implementacje
First
mają różne wartości zwracanych, więc stosuje się dwa poziomy zadnie: First
jest abstrakcyjną klasą bazową, aFirst *
służą do obsługi różnych instancji betonu.template <typename Type> class TypedFirst : public First
to typ abstrakcyjny, który definiuje funkcję z typem powrotuType
.- Wreszcie
ConcreteFirstX
są konkretne specjalizacjeTypedFirst<Type>
.
W tree.tpp
, dlaczego wywołanie new TF(this)
nie produkować błąd invalid use of incomplete type
? (Plamka jest oznaczona w kodzie) Myślę, że błąd nie powinno tam być, ponieważ podczas TF
jest szablon, kiedy za pomocą ConcreteFirstA
The tree.tpp
nie jest tego świadomy (nie obejmuje concretefirsta.h
lub nawet first.h
, to tylko forward deklaruje First
)
Pełny, nadający się do kompilacji i działający kod dla tego przykładu można znaleźć here on pastebin. Tutaj, będę wykluczać strażników i podobne rzeczy, dla zwięzłości. Kod jest w następujący sposób:
// tree.h
class First;
class Tree{
public:
Tree() {}
~Tree() {}
template<class TF> // where TF is a ConcreteFirst
void addFirstToTree();
private:
std::map<std::string, First *> firstCollection; // <- "First"'s here
};
#include "tree.tpp"
// tree.tpp
#include "tree.h"
template <class TF> // where TF is a ConcreteFirst
void Tree::addFirstToTree(){
this->firstCollection[TF::name] = new TF(this); // <--- Why does this work?
// ^^^^^^^^^^^^^
}
// first.h
class Tree;
class First{
public:
static const std::string name;
First(const Tree *baseTree) : myTree(baseTree) {}
virtual ~First();
protected:
const Tree *myTree;
};
template <typename Type> class TypedFirst : public First{
public:
static const std::string name;
TypedFirst(const Tree *baseTree) : First(baseTree) {}
Type &value() {return this->_value;}
private:
Type _value;
};
#include "first.tpp"
// first.tpp
#include "first.h"
template <typename Type>
const std::string TypedFirst<Type>::name = "default typed";
// first.cpp
#include "first.h"
First::~First() {}
const std::string First::name = "default";
// concretefirsta.h
#include "first.h"
class ConcreteFirstA : public TypedFirst<int>{
public:
static const std::string name;
ConcreteFirstA(const Tree *baseTree) : TypedFirst<int>(baseTree) {}
~ConcreteFirstA() {}
};
// concretefirsta.cpp
#include "concretefirsta.h"
const std::string ConcreteFirstA::name = "firstA";
Wreszcie kod, który przynosi to wszystko razem sprawia, że (w) odpowiednie wywołania funkcji:
// main.cpp
#include "tree.h"
#include "first.h"
#include "concretefirsta.h"
int main(){
Tree *myTree = new Tree();
myTree->addFirstToTree<ConcreteFirstA>(); // <-- here! why is this working?
delete myTree;
return 0;
}
DISCLAIMER To pytanie było zmotywowane przez większy problem, który miałem, który uważałem za zbyt duży i niemożliwy do odpowiedzi w formacie Stack Overflow. Chociaż początkowo starałem się o to zapytać, pytanie zostało zamknięte jako zbyt szerokie i teraz próbuję je uratować, zadając tylko część pytania.
Mój problem polega na tym, że Ciągle otrzymuję błąd w kawałku kodu o identycznej strukturze do tego: ale nie mogę go odtworzyć w małym przykładzie.
Zatem pytam dlaczego następujący fragment kodu jest nie produkujących błądinvalid use of incomplete type
(jak bym się spodziewał) i mam nadzieję, że pomoże mi zrozumieć i rozwiązać mój rzeczywisty problem.
Proszę, nie mów mi, że jest to przypadek the XY problem: Wiem, że nie pytam o mój faktyczny problem, ponieważ ja (i społeczność) uważałem, że jest zbyt duży dla tego formatu.
Czy próbowałeś "odejmowanie" wycinania kodu, dopóki błąd kompilacji nie zniknie? Inną techniką jest wstępne przetworzenie problematycznego pliku src i rozpoczęcie odgałęzienia dużego zakresu kodu, aż kompiluje się bez tego błędu. Zakładam, że używasz jakiejś kontroli wersji do łatwego wycofania. – greatwolf