【问题标题】:How to pass non-static member function as template argument to another member function?如何将非静态成员函数作为模板参数传递给另一个成员函数?
【发布时间】:2020-12-31 15:55:06
【问题描述】:

我想做这样的事情:

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,为什么x.mf 没有解析?我该如何进行这项工作?

【问题讨论】:

  • 一个问题是您需要将一个指针传递给函数。

标签: c++ class templates c++17 member-function-pointers


【解决方案1】:

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

你想传递一个成员函数指针到S::mflike 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>();
}

【讨论】:

  • 谢谢!你能给我一些关键字来查找(this-&gt;*f) 的特殊用法和&amp;S::mf 的需要吗?我也尝试使用 std::function 代替 auto 但无法使其工作。我将其更改为此版本,但仍然无法使用 std::function。在这种情况下 f 究竟推导出了什么?
  • @RexYuan 你要找的关键词是“成员函数指针”
【解决方案2】:

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);
}

【讨论】:

  • 使用auto 模板,我们可以毫无问题地传递对函数的引用。没有自动,我们仍然可以做到,但我们必须提前知道类型。
  • @AndyG 啊啊,谢谢你的信息。我什至不知道template &lt;auto&gt; 存在! (我是认真的)
  • 别对自己太苛刻,这是相当新的语法
【解决方案3】:

既然我已经实例化了x,为什么x.mf 没有解析?

因为它不是有效的语法。这里你需要通过运算符&amp; 提及成员函数,这意味着你应该有

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

这样模板参数就会被推导出为对应的成员函数指针。那是void(S::*)()


我该如何进行这项工作?

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

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

(this->*f)();

但是,由于,这是使用更通用的库函数的更方便的方式,因此在&lt;functional&gt; 标头中称为std::invoke

意味着你可以通过一个成员函数指针来做更具可读性的调用。

#include <functional> // std::invoke

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

See a demo

【讨论】:

    猜你喜欢
    • 2018-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-14
    • 1970-01-01
    • 2016-09-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多