给定两个或更多示例函数,是否可以编写模板化代码,这些代码能够推导出作为模板参数提供的函数的参数?
这是一个激励的例子:
void do_something(int value,double amount) { std::cout << (value * amount) << std::endl; } void do_something_else(std::string const& first,double & second,int third) { for(char c : first) if(third / c == 0) second += 13.7; } template<void(*Func)(/*???*/)> struct wrapper { using Args = /*???*/; void operator()(Args&& ... args) const { Func(std::forward<Args>(args)...); } }; int main() { wrapper<do_something> obj; //Should be able to deduce Args to be [int,double] obj(5,17.4); //Would call do_something(5,17.4); wrapper<do_something_else> obj2; //Should be able to deduce Args to be [std::string const&,double&,int] double value = 5; obj2("Hello there!",value,70); //Would call do_something_else("Hello there!",70); }
在/ * ??? * /的两种用法中,我试图弄清楚我可以放在哪里来启用这种代码.
由于Args在第一次使用之前没有被定义(以及我必须假设的还有许多语法错误),以下似乎不起作用,即使它确实如此,我仍然在寻找一个版本不需要明确写出类型本身:
template<void(*Func)(Args ...),typename ... Args) struct wrapper { void operator()(Args ...args) const { Func(std::forward<Args>(args)...); } }; wrapper<do_something,int,double> obj;
解决方法
使用C 17,我们可以使用自动模板非类型参数,这使得Wrapper< do_something>成为可能. w {}语法1).
至于演绎Args ……你可以用specialization做到这一点.
template <auto* F> struct Wrapper {}; template <class Ret,class... Args,auto (*F)(Args...) -> Ret> struct Wrapper<F> { auto operator()(Args... args) const { return F(args...); } };
Wrapper<do_something> w{}; w(10,11.11);
1)没有C 17,就不可能有Wrapper< do_something> w {}很好的语法.
你能做的最好的事情是:
template <class F,F* func> struct Wrapper {}; template <class Ret,auto (*F)(Args...) -> Ret> struct Wrapper<Ret (Args...),F> { auto operator()(Args... args) const { return F(args...); } };
Wrapper<declype(do_something),do_something> w{};