是否可以推迟过载决议?

Is it possible to defer overload resolution?

我正在尝试重载

int foo(int,int);
int foo(int);

int main() {           
    //decltype(foo) x;  // error: reference to overloaded function could not be resolved;
    decltype(foo(1)) f;      
}

我知道除非我选择其中一个重载,否则我无法获得指向 foo 的指针,但我想知道为什么重载集没有类型?写成

岂不是很自然
template <typename F>
void foofoo(F f,bool x) {
    if (x) f(1);
    else f(1,0);
}

并将其命名为 foofoo(foo,true); ?我知道有不同的方法可以编写类似的东西,但我特别想知道重载集。无论如何,我的问题是

在选择其中一个重载之前,我可以对重载集做些什么吗?

换句话说,是否有一些 magic 可以使下面的 true 照字面意思?

std::is_same_v< decltype( foo(1,1) ), magic<foo,int,int>::type >;

或者这通常是不可能的,因为 foo 未解决?

您可以使用重载函数集的名称做的事情很少,这些事情不需要立即解析为一个特定的函数(或函数模板特化)。但是,许多语义检查以某种方式获得 "delayed" 的上下文是在模板内部。通用 lambda 是编写模板的快捷方式。所以我们可以做的一件事是:

#include <utility>

#define WRAP_OVERLOADS(f) [](auto&& ...args) { \
    return f(std::forward<decltype(args)>(args)...); }

int foo(int, int);
int foo(int);

int main() {
    auto f = WRAP_OVERLOADS(foo);
    f(1);
    f(2,3);
}

尽管预处理器 #define 是必需的,因为无法表示要调用以传递给模板的函数的名称。 (函数指针可以是模板参数,也可以帮助推断模板函数参数的类型,但随后您又需要一个特定的重载才能使用模板。)