如何将非静态成员函数作为模板参数传递给另一个成员函数?

问题描述

我想做这样的事情:

struct S
{
   void mf() {};

   template <auto f>
   void func()
   {
      f();
   }
};

int main()
{
   S x;
   x.func<x.mf>();
}

但是,这些是错误:

error: no matching function for call to 'S::func<x.S::mf>()'`
note: candidate: 'template<auto f> void S::func()'
note:   template argument deduction/substitution failed:
error: could not convert 'x.S::mf' from '<unresolved overloaded function type>' to 'void (S::*)()'

我不确定我做错了什么。

为什么x.mf因为我已经实例化x而无法解决?而我该如何做呢?

解决方法

通过指针调用成员函数非常棘手。

您要将成员函数指针传递给S::mf like so

struct S
{
    void mf () {std::cout << "called mf\n";};

    template <auto f>
    void func ()
    {
        (this->*f)(); 
    }
};

int main()
{
    S x;
    x.func<&S::mf>();
}
,

x.mf不是类型,而是成员函数指针。 我们必须将其作为参数传递。

这是您修改的示例(不确定您要做什么)。

#include <iostream>

struct S
{
    int i=123;

    void mf () { std::cout << "i=" << i << '\n'; };

    template <typename f>
    void func (f fnct)
    {
        (this->*fnct)();   
    }
};

int main()
{
    S x{456};
    
    x.func(&S::mf);
}
,

为什么x.mf因为我已经实例化了x而无法解决?

因为它不是有效的语法。那里您需要提及操作员&的成员函数,这意味着您应该拥有

x.func<&S::mf>();
//    ^^^^^^^^

以便将模板参数推导为相应的成员函数指针。那就是void(S::*)()


我如何进行这项工作?

第二个问题是,函数调用f()应该是call through a member function pointer。这与普通的函数调用不同。

用实例调用成员函数指针的传统方式是

(this->*f)();

但是,由于是使用更通用的自由函数(从std::invoke头开始称为<functional>)的更方便的方式。

这意味着您可以通过类似成员函数指针的方式进行更具可读性的调用。

#include <functional> // std::invoke

template <auto f>
void func()
{
   std::invoke(f,this);
}

See a demo

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...