让我们考虑一下:
void goo () {
std::cout << "void goo ()\n";
}
int goo (int) {
std::cout << "int goo (int)\n";
return 42;
}
现在我想使用如下定义的包装函数来调用这些函数之一:
template <typename F, typename... A>
void c (F&& f, A&&... a) {
f (std::forward<A> (a)...);
}
与用法:
c (&goo, 10); // (X)
c (&goo); // (Y)
两种情况都会失败(GCC 5.3.1)并出现适当的错误:
error: no matching function for call to ‘c(<unresolved overloaded function type>, int)’
error: no matching function for call to ‘c(<unresolved overloaded function type>)’
就我而言,失败是因为编译器在必须初始化时无法选择适当的重载f
对象(信息太少)。
作为解决方案,我当然可以编写这样的使用调用:
c (static_cast<int (*) (int)> (&goo), 10);
c (static_cast<void (*) ()> (&goo));
告诉编译器我真正想使用哪个指针。
写这个static_cast
对我来说,代码变得更加丑陋,所以我编写了一个包装函数,用于使用模板将函数指针转换为适当的指针:
template <typename R, typename... Args>
using Funptr_t = R (*) (Args...);
template <typename R, typename... Args>
Funptr_t<R, Args...> funptr (Funptr_t<R, Args...> ptr) {
return static_cast<Funptr_t<R, Args...>> (ptr);
}
现在用法看起来好多了:
c (funptr<int, int> (&goo), 10);
c (funptr<void> (&goo));
我的问题是:您对如何处理这种情况有更好的想法吗?我很确定这种情况在通用代码中经常发生。所以,请给我一些建议。
理想的解决方案是如果我可以直接使用 (X) 和 (Y),那么可以使用以下方法来完成指向适当重载的魔术A...
并对调用者隐藏。