给定两个或更多示例函数,是否可以编写模板化代码来推断作为模板参数提供的函数的参数?
这是激励人心的例子:
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!", value, 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, class... Args, auto (*F)(Args...) -> Ret>
struct Wrapper<Ret (Args...), F>
{
auto operator()(Args... args) const
{
return F(args...);
}
};
Wrapper<declype(do_something), do_something> w{};
关于c++ - 如何从函数指针推导出参数列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46533698/