Templates 在typedef中实例化类型不完整的列表

Templates 在typedef中实例化类型不完整的列表,templates,typedef,clang,libc++,Templates,Typedef,Clang,Libc++,我在编译llvm时遇到问题。问题是我当前的编译器(clang+libc++)试图在定义模板参数之前实例化模板。下面是代码示例: // ----- TYPEDEFS ----- class NodeEntry; class EdgeEntry; typedef std::list<NodeEntry> NodeList; typedef std::list<EdgeEntry> EdgeList; typedef NodeList::iterator NodeItr;

我在编译llvm时遇到问题。问题是我当前的编译器(clang+libc++)试图在定义模板参数之前实例化模板。下面是代码示例:

// ----- TYPEDEFS -----
class NodeEntry;
class EdgeEntry;

typedef std::list<NodeEntry> NodeList;
typedef std::list<EdgeEntry> EdgeList;

typedef NodeList::iterator NodeItr; // line 39 
typedef NodeList::const_iterator ConstNodeItr;

typedef EdgeList::iterator EdgeItr;
typedef EdgeList::const_iterator ConstEdgeItr;

typedef std::list<EdgeItr> AdjEdgeList;

typedef AdjEdgeList::iterator AdjEdgeItr;

class NodeEntry {
private:  
  AdjEdgeList adjEdges;
  ...
};

class EdgeEntry {
private:
  AdjEdgeItr node1AEItr, node2AEItr;
  ...
};
/----TYPEDEFS-----
类节点;
阶级边缘化;
typedef std::列表节点列表;
typedef标准::列表边缘列表;
typedef节点列表::迭代器节点列表;//第39行
typedef节点列表::const_迭代器ConstNodeItr;
类型定义EdgeList::迭代器EdgeItr;
typedef EdgeList::const_迭代器ConstEdgeItr;
typedef std::列表调整列表;
typedef-adgegilist::迭代器adgegitr;
类节点{
私人:
边缘主义者;
...
};
阶级边缘{
私人:
ADGEDGEITR node1AEItr,node2AEItr;
...
};
编译器的错误如下:

error: field has incomplete type 'PBQP::Graph::NodeEntry'

/Developer/Extras/llvm/include/llvm/CodeGen/PBQP/Graph.h:39:13: note: in instantiation of template class
  'std::__1::list<PBQP::Graph::NodeEntry, std::__1::allocator<PBQP::Graph::NodeEntry> >' requested here
typedef NodeList::iterator NodeItr;
        ^
/Developer/Extras/llvm/include/llvm/CodeGen/PBQP/Graph.h:31:11: note: forward declaration of 'PBQP::Graph::NodeEntry'
class NodeEntry;
错误:字段的类型“PBQP::Graph::NodeEntry”不完整
/Developer/Extras/llvm/include/llvm/CodeGen/PBQP/Graph.h:39:13:注意:在模板类的实例化中
此处请求了“std::_1::list”
typedef节点列表::迭代器节点列表;
^
/Developer/Extras/llvm/include/llvm/CodeGen/PBQP/Graph.h:31:11:注意:“PBQP::Graph::NodeEntry”的正向声明
类节点;
据我所知,编译器试图实例化
std::list
,以获得迭代器。此操作失败,因为尚未定义NodeEntry。当然,EdgeEntry正在使用NodeEntry,反之亦然

显而易见的问题是:如何修复它?
教育性的问题是:为什么编译器在定义类型时尝试实例化模板?难道不应该等到我们对清单做点什么吗

谢谢。

根据已经链接的,他们不愿意支持libc++中stl容器的不完整类型

有趣的是,以下代码不会用libc++编译:

#include <list>

struct Tree {
    // ... more stuff ...
    std::list<Tree> mChildren;
};
#包括
结构树{
//…更多的东西。。。
标准:列出儿童;
};
但这段代码编译得很好,因为列表的模板参数也依赖于模板参数:

template<typename T>
struct TreeT {
    // ... more stuff ...
private:
    std::list<TreeT<T> > mChildren;
};
模板
结构树{
//…更多的东西。。。
私人:
标准:列出儿童;
};
这让我感到奇怪,因为后者更复杂


在一个类似的例子中,它也包含了对ISO中关于模板中不完整类型的部分的引用,被作为一个备选方案提到,因为它显式地允许递归数据结构。我是在诊断一个类似问题时发现这篇文章的,这是我目前的解决方案。

如果你想保证对不完整类型的支持,最好的办法是为它们创建
唯一的\u ptr

typedef std::list<std::unique_ptr<NodeEntry>> NodeList;
typedef std::list<std::unique_ptr<EdgeEntry>> EdgeList;
typedef std::list节点列表;
typedef标准::列表边缘列表;
在过去,很多时候
std::list
都能正常工作。然而,对于C++11和
noexcept
规范,更可能需要一个完整的类型,这样才能验证
noexcept
规范

C++11保证
unique_ptr
shared_ptr
将起作用,尽管有严格的限制。例如,无论在哪里执行
~unique_ptr()
,类型都必须完整。但是你通常可以把这样的代码提纲到一个源代码中,并在那一点上包含完整的类型

unique_ptr
shared_ptr
是C++11 std::lib中唯一保证使用不完整类型的类模板。其他一切都是未定义的行为:

[关于功能的决议]/p2/b5:

特别是,在以下情况下,影响未定义:

  • 如果在实例化模板组件时将不完整类型(3.9)用作模板参数,除非该组件特别允许

如果出于某种原因,
std::list
不需要拥有指向不完整类型的指针,那么
std::list
的效果会更好。您可能还希望使用
vector
而不是
list
,因为移动指针(甚至
unique_ptr
)的成本相对较小。

在linux上使用clang++3.0和libc++(svn版本154095)似乎编译得很好。有趣。根据clang网站