删除的函数和 ADL
Deleted function and ADL
我遇到了以下涉及 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 版本进入重载 table。现在来看最后一个例子:除了已删除的函数之外,现在还有另一个未删除的同名函数:
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 版本。所以总而言之:
- 当前命名空间没有匹配函数导致调用 ADL 版本
- 在当前命名空间中只有删除的函数会导致错误,可能是因为根本没有发现 ADL 版本
- 在当前命名空间中有另一个未删除的函数会导致调用 ADL 版本。
我的问题:这种行为是故意的吗?如果是这样,标准的哪一部分规定了这一点?
编辑:忘了说我是用onlinegdb编译的,所以用了gcc/g++。
明确的编译器错误。引用C++标准草案(n4659)[dcl.fct.def.delete]/2:
A program that refers to a deleted function implicitly or explicitly,
other than to declare it, is ill-formed. [ Note: This includes calling
the function implicitly or explicitly and forming a pointer or
pointer-to-member to the function. It applies even for references in
expressions that are not potentially-evaluated. If a function is
overloaded, it is referenced only if the function is selected by
overload resolution. The implicit odr-use of a virtual function does
not, by itself, constitute a reference. — end note ]
过载解析不能 select 由 ADL 重载。所以这个函数不应该被引用。第二个代码示例是一个格式正确的 C++ 程序(如果丢失的包含指令放回原处)。
你提到用g++编译,注意这个issue是fixed in GCC 7.2.0
我遇到了以下涉及 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 版本进入重载 table。现在来看最后一个例子:除了已删除的函数之外,现在还有另一个未删除的同名函数:
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 版本。所以总而言之:
- 当前命名空间没有匹配函数导致调用 ADL 版本
- 在当前命名空间中只有删除的函数会导致错误,可能是因为根本没有发现 ADL 版本
- 在当前命名空间中有另一个未删除的函数会导致调用 ADL 版本。
我的问题:这种行为是故意的吗?如果是这样,标准的哪一部分规定了这一点?
编辑:忘了说我是用onlinegdb编译的,所以用了gcc/g++。
明确的编译器错误。引用C++标准草案(n4659)[dcl.fct.def.delete]/2:
A program that refers to a deleted function implicitly or explicitly, other than to declare it, is ill-formed. [ Note: This includes calling the function implicitly or explicitly and forming a pointer or pointer-to-member to the function. It applies even for references in expressions that are not potentially-evaluated. If a function is overloaded, it is referenced only if the function is selected by overload resolution. The implicit odr-use of a virtual function does not, by itself, constitute a reference. — end note ]
过载解析不能 select 由 ADL 重载。所以这个函数不应该被引用。第二个代码示例是一个格式正确的 C++ 程序(如果丢失的包含指令放回原处)。
你提到用g++编译,注意这个issue是fixed in GCC 7.2.0