我正在编写自己的std :: async模拟(必须回溯至Intel13 / gcc 4.4 STL),并且工作正常:
template <typename Func, typename ...Args>
struct return_value {
template <typename T>
using decayed = typename std::decay<T>::type;
using type = typename std::result_of<decayed<Func>(decayed<Args>...)>::type;
};
template <typename Func, typename ...Args>
typename return_value<Func,Args...>::type async(Func &&func, Args&&... args) {
return func(args...);
}
void run(int a, double b) {
printf("a: %i b: %f\n", a, b);
}
int main() {
async(run, 1, 3.14);
}
但是,如果我为run
添加了重载:
void run() {
printf("no args\n");
}
然后它无法正确解决:
<source>: In function 'int main()':
<source>:27:23: error: no matching function for call to 'async(<unresolved overloaded function type>, int, double)'
async(run, 1, 3.14);
^
<source>:14:43: note: candidate: 'template<class Func, class ... Args> typename return_value<Func, Args>::type async(Func&&, Args&& ...)'
typename return_value<Func,Args...>::type async(Func &&func, Args&&... args) {
^~~~~
<source>:14:43: note: template argument deduction/substitution failed:
<source>:27:23: note: couldn't deduce template parameter 'Func'
async(run, 1, 3.14);
^
Compiler returned: 1
如何将函数用作模板参数并正确推断给定参数的重载?
答案 0 :(得分:0)
除非您知道返回类型,否则我个人看不出消除过载歧义的方法。您可以假设最常见的返回类型为void
,然后这样做:(为简便起见,我正在简化您的示例)
template <class F, class... Args>
auto async(F f, Args... args)
{
return f(args...);
}
template <class... Args>
auto async(void (*f)(Args...), Args... args)
{
return f(args...);
}
void run();
void run(int, double);
auto test()
{
async(run); // calls run();
async(run, 1, 2.); // calls run(int, double);
}
这似乎给用户带来了麻烦和困惑。为什么当传递的函数返回void
而返回int
却不起作用时,它为什么起作用?所以我不推荐。
所以实际上,您唯一能做的就是让它掌握在用户手中。
为您的函数调用者提供一些解决方案:
async(static_cast<int(*)(int, double)>(run), 1, 2.);
我个人根本不喜欢这种方法。我不喜欢它的冗长,而且最不喜欢的是,我必须对应该真正隐含的东西保持明确。
async([] { return run(1, 2.); });
我喜欢这个。还不错。仍然有些冗长,但是比其他方法更好。
是的,宏,在C ++中。事不宜迟,就存在了(为简便起见,省略了完美的转发):
#define OVERLOAD(foo) [] (auto... args) { return foo(args...); }
async(OVERLOAD(run), 1, 2.);
我不会对此发表评论。我让你们每个人都来判断这个宏。