成员函数模板,用于在具有任意参数的数据成员上调用函数

问题描述 投票:0回答:2

我正在使用C ++ 11代码库,想知道如何在传递任意参数的成员类型上调用任何函数。 请注意,由于我正在使用C ++ 11,因此无法使用类似std::invoke的语言。

[我开始在Outer类中创建功能模板,但最初的尝试给了我一个编译错误。

#include <iostream>
#include <utility>
#include <type_traits>

struct Inner {
  void bar(int x) {
    std::cout << "Called: x=" << x << std::endl;
  }
};

struct Outer {
  explicit Outer(Inner *i) : b{i} {}
  void foo(int) {}
  Inner* b;

  template <typename Func, typename ... Args>
  void CallInner(Func&& f, Args&& ... args) {
    b->f(std::forward<Args>(args)...);
  }
};


int main() {
  Inner inner{};
  Outer outer(&inner);
  outer.CallInner(&Inner::bar, 5);
}

Try it out yourself

同样,我想使函数CallInner的签名与上面的示例代码保持不变。

c++ c++11 templates variadic-templates
2个回答
1
投票

由于f是一个成员函数的指针,因此在被调用之前需要先解除引用:

(b->*f)(std::forward<Args>(args)...);

1
投票

关于更改签名,您没有太多选择,因为至少需要一个附加模板。

正确的语法稍微复杂一些:

struct Outer {
  explicit Outer(Inner *i) : b{i} {}
  void foo(int) {}
  Inner* b;

    template <typename Ret, typename ...FuncArgs,  typename ... Args>
    void CallInner(Ret (Inner::*f)(FuncArgs...), Args&& ... args) {
        (b->*f)(std::forward<Args>(args)...);
  }
};

CallInner的第一个参数必须是方法指针,并且在模板上下文中,不仅需要使用一组可变参数模板参数FuncArgs对其进行模板化,还需要使用其返回类型Ret 。然后,您还需要第二组可变参数模板参数来转发要转发的参数(它们不一定与FuncArgs相同,因此需要单独的可变参数模板类型集)。

© www.soinside.com 2019 - 2024. All rights reserved.