Reputation: 3619
I came across some C++ code which looks roughly like this:
void (classA::*methodA)() const noexcept
{
&classA::methodB
};
Note: obviously I'm abstracting out the class name and method names in this example.
What is the purpose of methodA
?
Analysis of the code
methodB
, but without parentheses, so it doesn't appear to be calling the method&
which reads to me as take the address of
methodA
doesn't return anythingOverall it appears to be just referencing the address of
methodB.
Any suggestions as to what this is accomplishing?
Upvotes: 1
Views: 183
Reputation: 6332
The key information is that you're initializing a pointer to a member function (PMF) using brace initializer syntax. See the C++ FAQs on PMFs.
Here's your code illustrated and commented, with an alternate way to write the same thing that is less confusing because it uses a type alias:
#include <iostream>
// Declare a class with a non-static method
class classA
{
public:
void methodB() const noexcept { std::cout << "methodB\n"; }
};
int main()
{
// Declare a function pointer by the name of methodA
// and initialize it to point to classA::methodB
void (classA::*methodA)() const noexcept
{
&classA::methodB
};
// Create an instance of classA
const auto a = classA{};
// Call a method on our instance using the function pointer
(a.*methodA)();
////////////////////////////////////////////////////////////////
// A clearer equivalent of the above:
// Declare an alias for the function pointer type
using FnPtr = void (classA::*)() const noexcept;
// Create an instance of the function pointer type,
// also using brace initialization and pointing to `classA::methodB`
const auto method = FnPtr{ &classA::methodB };
// Call the function indirectly through the function pointer
(a.*method)();
}
See it live on Coliru, where it prints:
methodB
methodB
One even shorter method if you don't need to know the type (e.g., it's just a local variable, not a member of a class) is that you can use auto
to infer the type:
const auto someMethod = &classA::methodB;
(a.*someMethod)();
If you still don't want to type that alias out but need the type in a context where you can't use auto
, you could use decltype
to declare it:
// Alias using decltype
using FnPtr = decltype( &classA::methodB );
// Declare instance using decltype (e.g., as a class member)
decltype( &classA::methodB ) method = nullptr;
// ...
// set it later:
method = &classA::methodB;
// Define template param using decltype
auto fnPtrs = std::vector< decltype( &classA::methodB ) >{};
Upvotes: 2
Reputation: 206707
Any suggestions as to what this is accomplishing?
It is defining a variable named methodA
and initializing it to &classA::methodB
.
The type of the variable is
a pointer to a const
member function of classA
that takes no arguments, returns void
, and the member function does not throw any exceptions.
The variable is initialized to &classA::methodB
.
If you make it a one-liner, it would be:
void (classA::*methodA)() const noexcept {&classA::methodB};
which is equivalent to:
void (classA::*methodA)() const noexcept = &classA::methodB;
Upvotes: 1