GCC 无法解析带有默认参数和以下参数包的方法调用

Ber*_*nns 8 c++ gcc g++ c++17

由于歧义,GCC 是否允许拒绝以下代码?对我来说,它看起来像一个错误。它与 msvc、clang 和 icc 编译得很好。

见这里:https : //godbolt.org/z/9fsnhx

#include <iostream>

class A
{
public:
    template<typename T>
    void Foo(int={}){
        std::cout << "A";
    }

    template<
        typename... T
        ,typename... Args
    >
    void Foo(int={}, Args&&... args)
    {    
        std::cout << "B";
    }
};

int main()
{
    A a;
    a.Foo<int>();
}
Run Code Online (Sandbox Code Playgroud)

Bar*_*rry 1

我认为这是一个 gcc 错误。正如Oliv在评论中指出的那样,如果您为默认参数提供参数,gcc 会接受 - 但这在本例中应该是无关紧要的。

\n

这里需要指出的相关规则是[temp.deduct.partial],第 3 段:

\n
\n

用于确定排序的类型取决于完成部分排序的上下文:

\n
    \n
  • 在函数调用的上下文中,使用的类型是函数调用具有参数的函数参数类型。138
  • \n
\n
\n

(脚注说):

\n
\n

默认参数不被视为在此上下文中的参数;它们仅在选择函数后才成为参数。

\n
\n

第 11 段:

\n
\n

考虑上述因素后,如果函数模板 F 至少与函数模板 G 一样专用,反之亦然,并且如果 G 具有尾随函数参数包,而 F 没有对应的参数,并且如果 F 没有尾随函数参数包,则 F 比 G 更专业。

\n
\n

第 12 段:

\n
\n

在大多数情况下,如果并非所有模板参数都有值,则推导会失败,但出于部分排序的目的,如果模板参数未在用于部分排序的类型中使用,则模板参数可能会保持没有值。[注意:在非推导上下文中使用的模板参数被视为已使用。\xe2\x80\x94尾注] [示例

\n
template <class T> T f(int);            // #1\ntemplate <class T, class U> T f(U);     // #2\nvoid g() {\n  f<int>(1);                            // calls #1\n}\n
Run Code Online (Sandbox Code Playgroud)\n

\xe2\x80\x94结束示例]

\n
\n

简而言之,在此处考虑部分排序时:

\n
    \n
  1. 默认参数并不重要,我们只考虑将 anint作为第一个参数的两个函数模板。

    \n
  2. \n
  3. T一次过载和T...第二次过载无关紧要。它们不属于用于部分排序的类型集中,它们不是函数的参数。这与第 12 段中的示例类似,其中同样命名的模板参数T也不起作用。

    \n
  4. \n
\n

所以基本上我们在以下之间订购:

\n
void Foo(int);\ntemplate <typename... Args> void Foo(int, Args&&...);\n
Run Code Online (Sandbox Code Playgroud)\n

这是一个非常简单的例子,第一个例子更加专业。gcc 出错了 - 我提交了96602

\n