Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to execute member-function-pointer with a smart pointer object?

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)();
}
like image 357
toaster_fan Avatar asked Nov 08 '19 11:11

toaster_fan


People also ask

How can we call member functions through a pointer to an object?

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 .

Can we call member function using this pointer?

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.

Can we call member function using this pointer in constructor?

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.

How do you call a function with a pointer in C++?

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.


1 Answers

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
     }
    
  • Secondly, dereferencing of the uninitialised 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
like image 53
JeJo Avatar answered Oct 16 '22 12:10

JeJo