为什么函数默认参数不能在 C++ 中完美转发?

Why function default parameters cannot be perferct forwarded in C++?

从我的角度来看,我发现了非常奇怪的行为:无法在下面的代码中转发函数默认参数。

void Test(int test = int{}) {}

template<typename F, typename ...Args>
void Foo(F&& f, Args&&... args)
{
    std::forward<F>(f)(std::forward<Args>(args)...);
}

int main()
{
    Foo(Test, 0); // This compiles
    Foo(Test);    // This doesn't compile
}

Clang 报告: 错误:函数调用的参数太少,预期为 1,实际为 0 GCC 和 VC 报告相同的错误。

谁能解释一下?

代码在这里: http://rextester.com/live/JOCY22484

Test 是一个总是接受一个参数的函数。如果在按名称调用 Test 时它的默认参数声明可见,则编译器将隐式地将默认参数添加到调用中。但是,一旦 Test 被转换为指针或函数引用,默认参数信息将不再可见。

这可以通过创建一个真正接受零个或一个参数并将该信息编码到其类型中的仿函数来解决,这样它就不会被破坏,就像这样:

struct Test {
    void operator()(int) { /* ... */ }
    void operator()() { operator(int{}); }
} test;
// ...
Foo(test, 0); // ok
Foo(test);    // ok