【问题标题】:Forwarding arguments to template member function将参数转发给模板成员函数
【发布时间】:2015-11-08 02:30:28
【问题描述】:

ideone example


我需要将一些预定义的参数和一些用户传递的参数转发给成员函数。

#define FWD(xs) ::std::forward<decltype(xs)>(xs)

template<class T, class... Ts, class... TArgs>
void forwarder(void(T::*fptr)(Ts...), TArgs&&... xs)
{
    T instance;
    (instance.*fptr)(FWD(xs)..., 0);
    //                           ^
    // example predefined argument
}

forwarder(&example::f0, 10, 'a');   
forwarder(&example::f1, 10, "hello", 5);

这适用于非模板成员函数。

传递给forwarder 的成员函数指针也可以指向模板函数。不幸的是,在这种情况下,编译器无法推断出T 的类型:

struct example
{
    void f0(int, int) { }

    template<class T>
    void f1(T&&, int) { }
};

// Compiles
forwarder(&example::f0, 10);

// Does not compile
forwarder(&example::f1, 10);

错误:

prog.cpp:30:28: error: no matching function for call to 'forwarder(<unresolved overloaded function type>, int)'
  forwarder(&example::f1, 10);
                            ^
prog.cpp:20:6: note: candidate: template<class T, class ... Ts, class ... TArgs> void forwarder(void (T::*)(Ts ...), TArgs&& ...)
 void forwarder(void(T::*fptr)(Ts...), TArgs&&... xs)
      ^
prog.cpp:20:6: note:   template argument deduction/substitution failed:
prog.cpp:30:28: note:   couldn't deduce template parameter 'T'
  forwarder(&example::f1, 10);

有什么方法可以帮助编译器推断出正确的类型而不改变forwarder的接口

如果不是,在不使用户语法过于复杂的情况下解决此问题的最佳方法是什么?

编辑: 将成员函数指针作为模板参数传递也是可以接受的,可能通过包装器。目标成员函数在编译时总是已知的。伪代码:

forwarder<WRAP<example::f0>>(10, 'a');
// Where WRAP can be a macro or a type alias.

ideone example

【问题讨论】:

  • 您仍然可以执行强制转换来解决歧义问题 (cf this fork of your example) 但我不确定这是否适合您...
  • 不知道这是否适合你,但coliru.stacked-crooked.com/a/3507a8671c1162c2
  • @Caninonos:对用户来说似乎太烦人了。如果没有其他更好的解决方案,我可以为所有传递的参数编写一个帮助器 forwarder 函数和一个扩展为 decltype 的简单宏......但我会保留它作为最后的手段。
  • @0x499602D2:这就是我在传递成员函数指针之前一直在做的事情......但是对于简单的函数来说,语法确实是样板。
  • 从函数参数推导模板类型对每个参数独立工作。如果您需要传递参数的类型来推断(或修复)(成员)函数指针的类型,您可以分两步执行推断;语法上例如forward(10, 'a').to(example::f0),其中 to 的定义类似于 template&lt;typename R, typename C&gt; auto to( R (C::*)(ForwardedArgs&amp;&amp;..., PredefinedArgs...) ); 请注意,这可能需要 cv- 和 reference-qualifiers 的各种组合。函数指针很不方便。

标签: c++ templates c++14 variadic-templates type-deduction


【解决方案1】:

我通过为成员函数指针提供模板参数,在 gcc 4.9 中编译了您的代码; 像这样

int main(){
// Compiles
forwarder(&example::f0, 10);
//Does not compile
forwarder(&example::f1, 10);
//Does compile, instantiate template with int or what ever you need
forwarder(&example::f1<int>,10)
}

我相信您需要实例化模板成员函数。 这会改变你的界面吗? 我认为任何答案都将围绕以某种方式实例化该成员模板。

【讨论】:

    猜你喜欢
    • 2021-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多