正如Vlad所说,引用的问题在于您需要一个最终对象。
好消息是,原则上,如果您有使用它的话,仍然可以拥有循环列表。
这是一件基本的事情,如果“下一个”元素是非空引用,则意味着总是有下一个元素,即列表要么是无限的,要么更现实的是,它会封闭在自身或另一个列表中。
进一步探究这个问题非常有趣而奇怪。
基本上唯一可能的事情是定义等效的节点(也代表列表)。
template<class T>
struct node{
T value;
node const& next;
struct circulator{
node const* impl_;
circulator& circulate(){impl_ = &(impl_->next); return *this;}
T const& operator*() const{return impl_->value;}
friend bool operator==(circulator const& c1, circulator const& c2){return c1.impl_ == c2.impl_;}
friend bool operator!=(circulator const& c1, circulator const& c2){return not(c1==c2);}
};
circulator some() const{return circulator{this};}
};
元素必须存在于堆栈中,而列表是静态的(好吧,引用无论如何都不能重新绑定),并且链接必须是const
引用!最终,value
可以显然地变为mutable
(可能是安全的?)。(此时,人们会想知道这与通过模数索引引用堆栈数组有何不同。)
构建node
/list对象的唯一方法是使用自身(或其他预先存在的节点)关闭它。因此,生成的列表要么是循环的,要么是“rho”形状。
node<int> n1{5, {6, {7, n1}}};
auto c = n1.some();
cout << "size " << sizeof(node<int>) << '\n';
do{
cout << *c << ", ";
c.circulate();
}while(c != n1.some()); //prints 5, 6, 7
我无法创建一个不是平凡可构造的节点(聚合体?)。
(添加任何基本构造函数都会因为我无法理解的原因在gcc
和clang
中产生分段错误)。
我也无法将节点封装在“容器”对象中,出现了同样奇怪的问题。
因此,对我来说,创建可以像这样构造的对象是不可能的:
circular_list<int> l{1,2,3,4}; // couldn't do this for obscure reasons
最后,由于无法构建适当的容器,因此不清楚这个对象的语义是什么,例如当两个“列表”相等时意味着什么?什么不意味着分配?或在不同大小的列表之间进行分配?
它是一个相当自相矛盾的对象,似乎没有一般价值或引用语义。
欢迎任何评论或改进!