Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing a pointer to a member function as a template argument. Why does this work?

Tags:

I have some code that 100% works for the use case I have. I'm just wondering if anyone can explain how and why it works.

I have a template class that sits between some code that handles threading and network communication and the library user to pass data received from the server to the user.

template <class Bar,           class Baz,           class BazReturnType,           void (Bar::*BarSetterFunction)(const BazReturnType &),           BazReturnType (Baz::*BazGetterFunction)(void) const> class Foo {     Foo( Bar *bar )         : m_bar(bar)     {     }      void FooMemberFunction( const Baz *baz )     {         boost::bind( BarSetterFunction, m_bar,                      boost::bind( BazGetterFunction, baz )() ) ();     }      Bar *m_bar; }; 

This template is instantiated and used in the library depending on the types of Bar and Baz like so:

typedef Foo<MyBar,             MyBaz,             ReturnTypeFromBazGetterFunction,             &MyBar::ActualSetterFunction,             &MyBaz::ActualGetterFunction >     MyFoo;  MyBar *bar = new MyBar; MyBaz *baz = new MyBaz; MyFoo *f = new MyFoo( bar ); f->FooMemberFunction( baz ); 

This all works and boost::bind calls the getter/setter functions to pass the data around where it needs to go. How and why does passing pointers to member functions as a template argument like in this case work?


In response to comments, I hadn't realized that pointers to member functions were valid template arguments. It's not something I had seen "in the wild" before. I tried it and it worked, but I wasn't expecting it to.

like image 505
Grant Limberg Avatar asked Dec 10 '09 17:12

Grant Limberg


People also ask

Which pointer is automatically passed to a member function when it is called?

When a member function is called, it is automatically passed an implicit argument that is a pointer to the invoking objects. This pointer is known as 'this' pointer.

Why would a pointer to a function be used?

A pointer to a function points to the address of the executable code of the function. You can use pointers to call functions and to pass functions as arguments to other functions.

How do you use pointers to member functions?

Using a pointer-to-member-function to call a function Calling the member function on an object using a pointer-to-member-function result = (object. *pointer_name)(arguments); or calling with a pointer to the object result = (object_ptr->*pointer_name)(arguments);

Can we call member function using this pointer?

You can use pointers to member functions in the same manner as pointers to functions. You can compare pointers to member functions, assign values to them, and use them to call member functions.


2 Answers

I think there is a better explanation why it is possible to do so than "because the standard says so":

The reason it works is because pointers-to-members are constant values known at compile time (pointer-to-member is effectively an offset of a member from the start of a class). Thus they can be used as parameters of templates, just as any other integer constant can be.

On the other hand, normal pointers are not compile time constants, because they depend on memory layout which only exists at runtime. They cannot be template arguments.

like image 156
kaalus Avatar answered Sep 23 '22 11:09

kaalus


When you ask a question along the lines of "why something works?", it implies that the fact that it works is somehow surprising to you. It is impossible to answer the question unless you explain why you find it surprising.

Why it works? Because the language specification explicitly says that it shall work. There's no other answer, until you explain your concerns in more detail.

like image 24
AnT Avatar answered Sep 23 '22 11:09

AnT