Why could the following library function make a call to a nonstatic member fuction without create an object?

60 views Asked by At

pb_ds (<ext/pb_ds/assoc_container.hpp> and 4 other headers) is a GNU C++ library for some data structures(e.g. red black tree). And I encountered the code of applying update when the tree is modified:

PB_DS_CLASS_T_DEC
template<typename Node_Update_>
inline void
PB_DS_CLASS_C_DEC::
apply_update(node_pointer p_nd, Node_Update_*  /*p_update*/)
{
  node_update::operator()(node_iterator(p_nd),
              node_const_iterator(static_cast<node_pointer>(0)));
}

where the node_update class is of the following form:

template<class Node_CItr,class Node_Itr,class Cmp_Fn,class _Alloc>
struct my_node_update
{
    typedef my_type metadata_type;
    void operator()(Node_Itr it, Node_CItr end_it)
    {
        //...
    }
};

and I was confused about the code node_update::operator()... which I think calls a non-static member function from the node_update class, but did not create an object. So how did the call work?

1

There are 1 answers

0
Thomas Mouton On

It's hard to know exactly without seeing the full definition of PB_DS_CLASS_C_DEC but :: is the scope resolution operator so it is using the rules for qualified name lookup to more fully specify under what scope the compiler should find the function operator() which is in this case node_update.

It's unclear without more context if node_update is a base class of PB_DS_CLASS_C_DEC, a namespace, a static member, or what.

I did find code almost the same as what you've pasted here

which looks like:

PB_DS_CLASS_T_DEC
template<typename Node_Update_>
inline void
PB_DS_CLASS_C_DEC::
apply_update(node_pointer p_nd, Node_Update_*)
{
  Node_Update_::operator()(node_iterator(p_nd, this),
               node_const_iterator(0, this));
}

If it is indeed an error that your code has node_update instead of Node_Update_ then they're instructing the compiler to utilize operator() in the templated type Node_Update_ which will presumably be deduced based on the arguments passed to apply_update.

From the above repo, apply_update is private and is always passed this as the second argument cast to a node_update type that the class itself is templated on and also publicly inherits from.

So the end result is that Node_Update_ always appears to be a base class and they're specifying which base type specifically to call operator() on.