![](/img/trans.png)
[英]Avoid template when initializing `std::priority_queue` with home-made `std::Compare`?
[英]C++ How to avoid friend template functions with home-made intrusive lists
我需要一个侵入式,已排序的双向链接列表。 我不想使用boost :: intrusive,所以我自己做这个,遇到了问题
对于双链表,有几个操作,这里只是其中之一,将有助于说明我的观点:
template<typename LIST, typename NODE>
void insertAfter(LIST *list, NODE *node, NODE *newNode)
{
newNode->prev_ = node;
newNode->next_ = node->next_;
if(nullptr == node->next_)
list->last_ = newNode;
else
node->next_->prev_ = newNode;
node->next_ = newNode;
}
现在假设我有一组对象在一个这样的列表中,但我希望其胆量是私有的:
struct Object
{
private:
Object *prev_, *next_;
};
现在,我创建我的列表(请忽略以下事实:当列表为空时,将出现nullptr异常...)。
struct List
{
Object *first_, *last_;
void addObject(Object *o)
{
insertAfter(this, last_, o); // not correct when list empty
}
};
因为prev_和next_是私有的,并且insertAfter没有访问权限,所以不会编译。 这可以很容易地解决:
// Fwd decl
struct List;
struct Object
{
friend void insertAfter<List, Object>(List *, Object *, Object *);
private:
Object *prev_, *next_;
};
struct List
{
Object *first_, *last_;
void addObject(Object *o)
{
insertAfter(this, last_, o);
}
};
但这打开了一个访问漏洞,任何人都可以使用insertAfter影响Object的私有成员。 我真正想要的是List成为Object的朋友。 我可以通过不在链接列表操作中使用模板来解决此问题(改为使用普通宏),但这显然有其缺点。 去这里的正确方法是什么?
沿着这些思路怎么样?
template<class ObjectType>
class List
{
ObjectType *first_, *last_;
public:
void addObject(ObjectType *o)
{
insertAfter(this, last_, o);
}
void insertAfter(ObjectType *node, ObjectType *newNode)
{
newNode->prev_ = node;
newNode->next_ = node->next_;
if(nullptr == node->next_)
this->last_ = newNode;
else
node->next_->prev_ = newNode;
node->next_ = newNode;
}
};
class Object
{
private:
Object *prev_, *next_;
friend class List<Object>;
};
int main() {}
不过,我看不出它的冒犯程度实际上不如您以前做的那么好:模板代码仍然是内联的,因此您不能阻止人们按照自己的喜好重写类。 放松一下,对客户保持合理的信任度:)
您可以封装侵入性数据,例如:
template <typename Object>
class List
{
public:
class PrivateData
{
friend class List;
public: // minimal stuff which should be public go here
PrivateData() : prev_(nullptr), next_(nullptr) {}
private:
// other stuff
Object *prev_, *next_;
};
// Other stuff
};
然后在您的对象中:
class Object
{
public:
List<Object>::privateData listData_;
private:
// internal data.
};
由于ListData
中的所有内容都是私有的,因此用户无法对listData_
进行任何操作,但可以由作为好友的List
访问。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.