如何定义递归类型?

时间:2014-08-29 07:36:50

标签: c++ c++11

我想要一份清单。列表中的条目将存储值以及迭代器到列表中的另一个条目。我该如何定义这种类型?它是这样的,但在语法上是正确的。

typedef list<pair<int, MyList::const_iterator>> MyList;

5 个答案:

答案 0 :(得分:8)

让我们用一堆用户定义的类型来彻底解决问题,以打破声明的递归:

struct Node {
    int _value;
    std::list<Node>::const_iterator _next;
};

如果你想使用typedef,你可以:

struct Node;
typedef std::list<Node> NodeList;

struct Node {
    int _value;
    NodeList::const_iterator _next;
};

编辑作为T.C.提醒我,实例化具有不完整类型的标准容器可能 未定义行为(某些标准库实现确保不是这样)。 所以,让我们把所有这些推迟到以后。

修改:嗯,这也无济于事。因此,请验证您的std::list实现是否支持不完整的类型(或信任它,这通常是诚实的),或使用Boost :: containers。

template <class = void>
struct Node_ {
    int _value;
    typename std::list<Node_>::const_iterator _next;
};

typedef Node_<> Node;

答案 1 :(得分:1)

列表中的迭代器不仅不会被插入或删除的其他元素无效,而且迭代器指向的元素也将保持不变。因此我们可以做到:

struct Element {
  int first;
  Element* second;
};

typedef list<Element> MyList;

这与您的要求非常相似,但second是指针而不是迭代器。如果你真的需要它作为迭代器,我们可以为std::list<>切换boost::intrusive::list<>(如果你不能使用Boost,可以为本土的侵入列表)。然后,value_type(即Element)实际上将包含prev / next指针,您可以将其用作迭代器。在Boost中,这个名为iterator_to(),在此解释:http://www.boost.org/doc/libs/1_43_0/doc/html/intrusive/obtaining_iterators_from_values.html

答案 2 :(得分:0)

如果你愿意,你可以这样做:

typedef list<pair<int, void*> > MyList;
typedef list<pair<int, void*> >::const_iterator MyListIterator;

int main() {
    MyList l;
    MyListIterator it;
    pair<int, void*> p(2, &it);
    l.push_back(p);
}

顺便说一下,我更喜欢John Zwinck的解决方案。

答案 3 :(得分:0)

您可以通过向前声明您的元素来实现这一点。

#include <list>

struct Element;
typedef std::list<Element> ElementList;

struct Element
{
    int value;
    ElementList::iterator element;
};

int main() {
    ElementList l;
    l.push_back({0, l.end()});
    l.push_back({1, l.begin()});
}

答案 4 :(得分:0)

使用boost::any或同等商品来存储iterator。由于迭代器往往很小,小对象优化会起作用,而开销也会很低。