1

我最近在侵入性列表的上下文中遇到了这段代码:

template<typename T> struct Node{
    T *next;
    T *prev;
    Node(): next(nullptr), prev(nullptr){}
};


/*
 * Intrusive doubly-linked-list
 *
 * */
template<typename T, Node<T> T::*NODE>
class List{
T *head;
T *tail;
public: 
    List():head(nullptr), tail(nullptr){}
    ~List() {clear();}

    /*
    * Add an element at the head of list
    * @param elem item to be inserted
    * */
    void add_to_front(T *elem){

        Node<T> *node = &(elem->*NODE);

        assert((node->next) == nullptr);
        assert((node->prev) == nullptr);

        node->next = head;

        if(head != nullptr){
            Node<T> *temp = &(head->*NODE);
            temp->prev = elem;
        }

        head = elem;

        if(tail == nullptr)
            tail = head;

    }
    //other member functions ,etc.
    ..
    ..
};

我在 boost侵入式列表库( member_hook<class T, class Hook, Hook T::* PtrToMember>)中看到了类似的代码。

我的问题是关于模板参数Node<T> T::*NODE。我不是 C++ 方面的专家,但我以前从未遇到过这种特殊的语法,也不知道要搜索什么来理解它。

这是什么意思?它的目的是什么,我应该将其解释为 - “ NODE 是指向节点的指针,属于 T ”?这对我来说没有意义,因为不知道 T 提前包含特定成员,据我所知,::它用于解析范围。

同样,如果有人可以澄清*NODE这一行中的用法,例如 : Node<T> *node = &(elem->*NODE);,那将有助于我理解它的用途。

4

2 回答 2

3

它是一个成员指针。NODE是指向T具有类型的成员的指针Node<T>

同样,foo->*bar(*foo).*barwhere .*is dereference-pointer-to-member 运算符的简写。访问由指向elem->*NODE的成员。*elemNODE

于 2016-10-26T20:33:45.227 回答
1

这就是所谓的“指向成员运算符的指针”。

标准(N3690,第 5.5 节)说:

成员指针运算符 ->* 和 .* 从左到右分组。

二元运算符 .* 将其第二个操作数(其类型为“指向 T 成员的指针”)绑定到其第一个操作数,该操作数应属于 T 类或 T 是明确且可访问的基类的类。结果是第二个操作数指定的类型的对象或函数。

二元运算符 ->* 将其第二个操作数绑定到其第一个操作数,该操作数应为“指向 T 成员的指针”类型,该操作数应为“指向 T”或“指向 T 是明确的类的指针”类型和可访问的基类。” 表达式 E1->*E2 被转换为等价形式 (*(E1)).*E2。

也看看http://en.cppreference.com/w/cpp/language/operator_member_access

运算符 ::* 是相同的——使用类名而不是变量进行访问,就像当您拥有类 C 和对象 obj 时,您可以使用 C::func 或 obj.func 或 (&obj)->func。

于 2016-10-26T20:35:36.560 回答