我遇到了以下涉及ADL和已删除功能的令人困惑的示例:
第一个例子:
namespace A
{
struct S{};
void f(S){cout << "adl" << endl;}
}
namespace C
{
//void f() = delete;
//void f (double);
void test()
{
A::S arg;
f(arg);
}
}
int main()
{
C::test();
return 0;
}
正如所料,A::f
是通过ADL调用的。在下一个示例中,C
中有一个删除的具有相同名称的函数:
namespace A
{
struct S{};
void f(S){cout << "adl" << endl;}
}
namespace C
{
void f() = delete;
//void f (double);
void testi()
{
A::S arg;
f(arg);
}
}
int main()
{
C::testi();
return 0;
}
编译失败,错误消息为error: use of deleted function 'void C::f()'
。显然,删除的函数会阻止ADL版本进入重载表。现在是最后一个例子:除了删除的函数之外,现在还有另一个未删除的函数,它具有相同的名称:
namespace A
{
struct S{};
void f(S){cout << "adl" << endl;}
}
namespace C
{
void f() = delete;
void f (double);
void testi()
{
A::S arg;
f(arg);
}
}
int main()
{
C::testi();
return 0;
}
运行它会执行f
的ADL版本。总之:
我的问题:这种行为是故意的吗?如果是这样,标准的哪一部分指定了这个?
编辑:我忘了提到我使用了onlinegdb进行编译,所以使用了gcc / g ++。
答案 0 :(得分:1)
明确的编译器错误。引用C ++标准草案(n4659)[dcl.fct.def.delete]/2:
隐式或明确引用已删除函数的程序, 除了宣布它之外,是不正确的。 [注意:这包括打电话 函数隐式或显式并形成指针或 指向函数的指针成员。它甚至适用于参考 没有潜在评估的表达式。 如果有功能的话 重载时,仅在选择函数时才引用它 重载决议。虚函数的隐式odr使用确实如此 本身并不构成参考。 - 结束说明]
过载分辨率无法通过ADL选择过载。所以不应该引用这个功能。第二个代码示例是一个格式良好的C ++程序(如果丢失的include指令被放回)。
您提到使用g ++进行编译,请注意此问题为fixed in GCC 7.2.0