由于歧义,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)
我认为这是一个 gcc 错误。正如Oliv在评论中指出的那样,如果您为默认参数提供参数,gcc 会接受 - 但这在本例中应该是无关紧要的。
\n这里需要指出的相关规则是[temp.deduct.partial],第 3 段:
\n\n\n用于确定排序的类型取决于完成部分排序的上下文:
\n\n
\n- 在函数调用的上下文中,使用的类型是函数调用具有参数的函数参数类型。138
\n
(脚注说):
\n\n\n默认参数不被视为在此上下文中的参数;它们仅在选择函数后才成为参数。
\n
第 11 段:
\n\n\n考虑上述因素后,如果函数模板 F 至少与函数模板 G 一样专用,反之亦然,并且如果 G 具有尾随函数参数包,而 F 没有对应的参数,并且如果 F 没有尾随函数参数包,则 F 比 G 更专业。
\n
第 12 段:
\n\n\n在大多数情况下,如果并非所有模板参数都有值,则推导会失败,但出于部分排序的目的,如果模板参数未在用于部分排序的类型中使用,则模板参数可能会保持没有值。[注意:在非推导上下文中使用的模板参数被视为已使用。\xe2\x80\x94尾注] [示例:
\nRun Code Online (Sandbox Code Playgroud)\ntemplate <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\xe2\x80\x94结束示例]
\n
简而言之,在此处考虑部分排序时:
\n默认参数并不重要,我们只考虑将 anint作为第一个参数的两个函数模板。
第T一次过载和T...第二次过载也无关紧要。它们不属于用于部分排序的类型集中,它们不是函数的参数。这与第 12 段中的示例类似,其中同样命名的模板参数T也不起作用。
所以基本上我们在以下之间订购:
\nvoid Foo(int);\ntemplate <typename... Args> void Foo(int, Args&&...);\nRun Code Online (Sandbox Code Playgroud)\n这是一个非常简单的例子,第一个例子更加专业。gcc 出错了 - 我提交了96602。
\n| 归档时间: |
|
| 查看次数: |
108 次 |
| 最近记录: |