Sono confuso sul motivo per cui il mio codice non produce l'errore invalid use of incomplete type
, mentre tutta la lettura che ho fatto su questo errore suggerisce che dovrebbe.
La domanda derivava da questo errore mostrando (come previsto) nella parte del mio codice con una struttura simile, ma non riesco a riprodurla in un piccolo esempio (vedere diniego alla fine del domanda).Uso non valido del tipo incompleto: perché non si verifica alcun errore in questo caso?
Sintesi di quello che sto cercando di fare:
- Ho una struttura (
Tree
), e voglio assegnare diversi oggetti di tipo di baseFirst
ad esso. - implementazioni concrete di
First
hanno valori di ritorno diverse, quindi due livelli di riferimento indiretto vengono utilizzati: First
è una classe base astratta, eFirst *
vengono utilizzati per gestire istanze concrete differenti.template <typename Type> class TypedFirst : public First
è un tipo astratto che definisce la funzione con tipo di ritornoType
.- Infine
ConcreteFirstX
sono specializzazioni concrete diTypedFirst<Type>
.
In tree.tpp
, perché la chiamata a new TF(this)
non produce l'errore invalid use of incomplete type
? (Il punto è segnato nel codice) Penso che l'errore dovrebbe essere lì perché, mentre TF
è un modello, quando utilizza ConcreteFirstA
, il tree.tpp
non è a conoscenza di esso (non include concretefirsta.h
o addirittura first.h
, è solo forward dichiara First
)
Il codice completo, compilabile e eseguibile per questo esempio può essere trovato here on pastebin. Qui, escluderò le protezioni #define
e simili, per brevità. Il codice è il seguente:
// 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";
Infine, il codice che mette tutto insieme e rende il (a) funzione appropriata chiamate:
// 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 Questa domanda è stata effettivamente motivata da un problema più grande che ho avuto, che ho ritenuto troppo grande e senza risposta in formato Stack Overflow. Anche se inizialmente ho provato a chiedermelo, la domanda è stata chiusa in quanto troppo ampia e ora sto cercando di recuperarla chiedendo solo una parte della domanda.
Il mio problema è che Continuo a ricevere l'errore in un pezzo di codice con struttura identica a questo: ma, non riesco a riprodurlo in un piccolo esempio.
Così, mi chiedo il motivo per cui il seguente pezzo di codice è non produrre l'erroreinvalid use of incomplete type
(come ci si aspetta), e spero che mi aiuterà a capire e risolvere il mio problema reale.
Per favore, non dirmi che questo è un caso di the XY problem: so che non sto chiedendo del mio problema reale, perché io (e la comunità) lo ritenevo troppo grande per questo formato.
Hai provato a "sottrarre" il codice finché l'errore di compilazione non scompare? L'altra tecnica consiste nel preprocessare il file src problematico e avviare lo stub di ampie porzioni di codice fino a quando non viene compilato senza quell'errore. Suppongo che tu stia usando una specie di controllo di versione per un facile rollback. – greatwolf