Executing a list with incomplete type in typedef

I have a problem compiling llvm. The problem is that my current compiler (clang + libc ++) tries to create a template before the template parameter is set. Here's some sample code:

// ----- 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;
  ...
};

      

Compiler error:

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;

      

As far as I can tell, the compiler is trying to instantiate std::list<NodeEntry>

in order to get the iterator. This fails because the NodeEntry has not yet been defined. And of course EdgeEntry uses NodeEntry and vice versa.

The obvious question is, how do you fix it?
Educational question: why is the compiler trying to create a template when defining a type? If he doesn't wait for us to do something with the list?

Thank.

+3


source to share


2 answers


If you need guaranteed support for incomplete types, your best bet is to create for them unique_ptr

:

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

      

In the past std::list<incomplete_type>

, it would just work many times . However, with the C ++ 11 specifications and noexcept

it becomes more and more likely that a complete type is needed, just so that validation noexcept

can be checked.

C ++ 11 guarantees that unique_ptr<incomplete_type>

and shared_ptr<incomplete_type>

will work, although there are strict restrictions. For example, wherever ~unique_ptr()

is executed, the type must be filled there. But you can usually point code like this to the source and # include the full type at this point.



unique_ptr<incomplete_type>

and shared_ptr<incomplete_type>

are the only class templates in C ++ 11 std :: lib that are guaranteed to work with incomplete types. Everything else is undefined behavior:

[res.on.functions] / p2 / b5:

In particular, the effects are undefined in the following cases:

...

  • if an incomplete type (3.9) is used as a template argument when instantiating a template component, unless specifically permitted for that component.

If for some reason you std::list

don't need to own a pointer to an incomplete type, then it std::list<NodeEntry*>

will work even better. You may also want to be entertained with help vector

instead list

, as the cost of moving signs (or even unique_ptr

) around is relatively low.

+3


source


According to the clang docs also linked already, they don't want to support incomplete types for stl containers in libc ++.

Something funny is that the following code won't compile with libC ++:

#include <list>

struct Tree {
    // ... more stuff ...
    std::list<Tree> mChildren;
};

      

but this code compiles fine as the list template parameter also depends on the template parameter:



template<typename T>
struct TreeT {
    // ... more stuff ...
private:
    std::list<TreeT<T> > mChildren;
};

      

This seems strange to me, since the latter is more complicated.

In a similar post, which also refers to the ISO section on incomplete types in templates, Boost.Container is mentioned as an alternative because it explicitly allows recursive data structures. I came across this post while diagnosing a similar issue and this is my solution for now.

+2


source







All Articles