【发布时间】:2014-09-25 13:56:15
【问题描述】:
我对为什么我的代码没有产生错误invalid use of incomplete type 感到困惑,而我对这个错误所做的所有阅读都表明它应该出现。
问题源于这个错误的出现(如预期的那样)在我的代码部分具有类似的结构,但我无法在 small 示例中重现它(请参阅问题末尾的 disclaimer) .
我正在尝试做的总结:
- 我有一个结构 (
Tree),我想为它分配基本类型为First的不同对象。 -
First的具体实现有不同的返回值,因此使用了两个级别的间接: -
First是抽象基类,First *用于处理不同的具体实例。 -
template <typename Type> class TypedFirst : public First是一个抽象类型,定义了返回类型为Type的函数。 - 最后
ConcreteFirstX是TypedFirst<Type>的具体特化。
在tree.tpp 中,为什么对new TF(this) 的调用不 会产生invalid use of incomplete type 错误? (代码中标记了该点)我认为错误应该在那里,因为虽然TF是一个模板,但当我使用ConcreteFirstA时,tree.tpp不知道它(它不包括concretefirsta.h甚至first.h,它只向前声明First)
可以在here on pastebin 找到此示例的完整、可编译和可运行代码。在这里,为简洁起见,我将排除 #define 警卫和类似的东西。代码如下:
// 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";
最后,将所有这些结合在一起并进行(不)适当的函数调用的代码:
// 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;
}
免责声明这个问题实际上是由我遇到的一个更大的问题引起的,我认为这个问题太大了,无法以 Stack Overflow 格式回答。尽管我最初尝试询问它,但这个问题被关闭得太宽泛了,我现在正试图通过只询问部分问题来挽救它。
我的问题是 我在一段结构与此代码相同的代码中不断收到错误:但是,我无法在一个小例子中重现它。
因此,我在问为什么下面的代码不会产生错误invalid use of incomplete type(正如我所料),我希望这对我有帮助了解并解决我的实际问题。
请不要告诉我这是the XY problem 的情况:我知道我不是在问我的实际问题,因为我(和社区)认为它对于这种格式来说太大了。
【问题讨论】:
-
您是否尝试过“减法”删除代码,直到编译错误消失?另一种技术是预处理有问题的 src 文件并开始删除大量代码,直到它编译没有错误。我假设您正在使用某种版本控制来轻松回滚。
标签: c++ templates incomplete-type