I am trying to execute a member-function
of a class with a smart pointer instance. The address of this function is passed by value, which I want to call though a smart pointer instance of the respective class.
I already tried this:
(registerList.*setRegister)();
But it errors out:
no match for ‘operator->*
Register
class member function:
uint16_t Registers::getSP()
{
return this->sp;
}
The code snippet:
std::unique_ptr<Registers> registerList;
SetRegisteropcodeLdWordRegister(&Registers::getSP)
void opcodeLdWordRegister(uint16_t (*Registers::setRegister)())
{
(registerList.*setRegister)();
}
The pointer to member operators . * and ->* are used to bind a pointer to a member of a specific class object. Because the precedence of () (function call operator) is higher than . * and ->* , you must use parentheses to call the function pointed to by ptf .
Function pointer to member function in C++ In C++ , function pointers when dealing with member functions of classes or structs, it is invoked using an object pointer or a this call. We can only call members of that class (or derivatives) using a pointer of that type as they are type safe.
the constructor is the first function which get called. and we can access the this pointer via constructor for the first time. if we are able to get the this pointer before constructor call (may be via malloc which will not call constructor at all), we can call member function even before constructor call.
To pass the value by pointer, argument pointers are passed to the functions just like any other value. So accordingly you need to declare the function parameters as pointer types as in the following function swap(), which exchanges the values of the two integer variables pointed to by its arguments.
First of all, your shown code and the error message does not match. For the given code you should be getting (from clang) following error message
error: left hand operand to .* must be a class compatible with the right hand operand, but is 'std::unique_ptr<Registers>'
(registerList.*setRegister)();
^
This can be solved by dereferencing the pointer(like in @Caleth's answer):
((*registerList).*setRegister)();
Now the error message that was shown in the question: no match for ‘operator->*
should be coming when you would have tried the following syntax.(Minimal reproducible code)
(registerList->*setRegister)();
This is because smart pointers do not have the pointer-to-member access operator defined in the standard. Therefore, you need to go for dereferencing the smart pointer via operator*
or by member function std::unique_ptr::get
, and call the member function.
Using the member std::unique_ptr::get
the correct syntax would be (See the live demo online)
(registerList.get()->*setRegister)()
That being said, if you have access to c++17 use unified version of function invoker std::invoke
to invoke the member function with the respective instance, by which you can forget about the (maybe)complicated syntax for operator->*
.
Your code has a couple of issues too:
The member function pointer type in your opcodeLdWordRegister
is
wrong.It should have been
return_type(Class_name::* variable_name)(/*parameters_types, if any*/)
Following is the fixed version.
#include <functional> // std::invoke
void opcodeLdWordRegister(uint16_t(Registers:: * setRegister)())
// ^^^^^^^^^^^^^^^^^^^^^^^^^ >>> correct syntax
{
std::invoke(setRegister, registerList);
// ^^^^^^^^^^^ member function
// ^^^^^^^^^^^^ instance
}
registerList
pointer
will cause UB.Following is the demonstrative minimal complete example for the case: (See the live demo online)
#include <iostream>
#include <functional> // std::invoke
#include <memory> // std::unique_ptr
class Registers
{
uint16_t sp{2}; // member initialized with 2
public:
uint16_t getSP() const // function can be marked const as it does not alter the member
{
return this->sp;
}
};
auto registerList = std::make_unique<Registers>(); // initialized the pointer with default object
void opcodeLdWordRegister(uint16_t(Registers::*setRegister)() const)
// ^^^^^^^^^^^^^^^^^^^^^^^^^ correct syntax
{
std::cout << std::invoke(setRegister, registerList);
}
int main()
{
opcodeLdWordRegister(&Registers::getSP);
return 0;
}
Output:
2
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With