2014-01-24 6 views
0

침입, 정렬, 이중 연결 목록이 필요합니다. 나는 boost :: intrusive를 사용하고 싶지 않다. 그래서 나는이 일을하고 있고, 문제가되고있다.C++ 자택 침입 목록으로 친구 템플릿 기능을 피하는 방법

이중 연결리스트에는 몇 가지 연산이있다. 여기에 하나의 설명이있다. 포인트 :

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의 친구가되는 것입니다. 필자는 연결된 목록 작업 (대신 일반 매크로 사용)에 대한 템플릿을 사용하지 않음으로써이 문제를 해결할 수 있지만 분명히 단점이 있습니다. 여기에 가려면 옳은 길은 무엇입니까?

+0

왜'std :: list' (http://www.cplusplus.com/reference/list/list/)를 사용하지 않는가? – Sean

+2

'나는 싫어. boost :: intrusive를 사용하려면이 작업을 스스로하고 있습니다 .'이 작업을 확장 할 수 있습니까? –

+0

@ LightnessRacesinOrbit, 내가 정말로 목표로 삼고있는 것은 항상 정렬 된 이중 연결 목록입니다. "항상 정렬 됨"은 insert() 메서드가 이제 O (n)이고 비교자를 사용하여 항목을 정렬 된 위치의 목록에 배치한다는 것을 의미합니다. 그리고 침입 성이 필요합니다 ... 침입 차단 목록을 보았습니다 : http://www.boost.org/doc/libs/1_55_0/doc/html/intrusive/list.html 그리고 그것은 정렬 요구 사항을 만족시키지 못합니다. – Badmanchild

답변

1

어떨까요?

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() {} 

는하지만, 이미 해왔 던 것보다 정말 덜 불쾌 어떻게 볼 수 없습니다 : 템플릿 코드 어쨌든 인라인, 그래서 당신은 자신의 취향에 맞게 클래스를 다시 작성에서 사람들을 중지 할 수 없습니다. 그냥 긴장을 풀고 고객에게 합리적인 수준의 신뢰를 얻으세요 :)

0

당신은 관입 데이터를 캡슐화 할 수 있습니다, 뭔가 같은 : 사용자가 아무것도를 개인 할 수 있습니다 ListData의 모든 것을 같이

class Object 
{ 
public: 
    List<Object>::privateData listData_; 
private: 
    // internal data. 
}; 

: 개체에 다음

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 

}; 

그리고 listData_ 하지만 친구 인 List에 액세스 할 수 있습니다.