Что означает аргументы шаблона этого типа - `ClassA<T> T:: * ELEM`?

Я недавно сталкивался с этим кодом в контексте навязчивых списков:

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.
    ..
    ..
};

Я вижу похожий код в библиотеке интрузивных списков (member_hook<class T, class Hook, Hook T::* PtrToMember>).

Мой вопрос касается аргумента шаблона Node<T> T::*NODE, Я не эксперт в C++, но я никогда раньше не сталкивался с этим конкретным синтаксисом и не знаю, что искать, чтобы понять его.

Что это значит? Какова его цель, и что я должен интерпретировать как "NODE - это указатель на узел, принадлежащий T"? Это не имеет смысла для меня, потому что T, как известно, не содержит конкретных членов заранее, и, насколько я знаю, :: используется для разрешения области.

А также, если кто-то мог бы уточнить использование *NODE в этой строке, например: Node<T> *node = &(elem->*NODE);, это помогло бы мне понять, для чего это используется.

2 ответа

Решение

Это указатель на член. NODE это указатель на член T это имеет тип Node<T>,

Так же, foo->*bar это сокращение для (*foo).*bar где .* является оператором разыменования-указателя на член. elem->*NODE получает доступ к члену *elem указал на NODE,

Это называется "указатель на член оператора".

Стандарт (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.

Другие вопросы по тегам