如何使用智能指针对象执行成员函数指针?

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

我正在尝试使用智能指针实例执行 class 的 member-function。这个函数的地址是按值传递的,我想通过相应 class.

的智能指针实例来调用它

我已经试过了:

(registerList.*setRegister)();

但它出错了:

no match for ‘operator->*

Register class成员函数:

uint16_t Registers::getSP()
{
    return this->sp;
}

代码片段:

std::unique_ptr<Registers> registerList;

SetRegisteropcodeLdWordRegister(&Registers::getSP)

void opcodeLdWordRegister(uint16_t (*Registers::setRegister)()) 
{
        (registerList.*setRegister)();
}

首先,您显示的代码与错误消息不匹配。对于给定的代码 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)();
            ^

这可以通过取消引用指针来解决(就像@Caleth 的回答):

((*registerList).*setRegister)();

现在问题中显示的错误消息:no match for ‘operator->* 应该在您尝试以下语法时出现。(Minimal reproducible code)

(registerList->*setRegister)();

这是因为智能指针没有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,调用了成员函数

使用成员 std::unique_ptr::get 正确的语法是 (See the live demo online)

(registerList.get()->*setRegister)()

话虽这么说,如果您有权访问 use unified version of function invoker std::invoke 来调用相应实例的成员函数,您就可以忘记 operator->* 的(可能)复杂的语法。

您的代码也有几个问题:

  • opcodeLdWordRegister中的成员函数指针类型是 wrong.It 应该是

    return_type(Class_name::* variable_name)(/*parameters_types, if any*/)
    

    以下是固定版本。

    #include <functional>  // std::invoke
    
    void opcodeLdWordRegister(uint16_t(Registers:: * setRegister)())
    //                                 ^^^^^^^^^^^^^^^^^^^^^^^^^ >>> correct syntax
    {   
        std::invoke(setRegister, registerList);
        //          ^^^^^^^^^^^                 member function
        //                       ^^^^^^^^^^^^   instance
     }
    
  • 其次,取消引用未初始化的registerList指针 会导致UB。

以下是该案例的示范性最小完整示例:(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;
}

输出:

2

如果您没有 std::invoke,您仍然可以执行它会执行的操作,即取消引用调用站点中的(唯一)指针。

((*registerList).*setRegister)();