[英]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.