考虑下面的代码,其中重载的位置f
会导致一些非直观的行为。该代码在 Clang 3.4.1 和 gcc 4.8 中编译时都没有警告。
template<typename T>
struct A
{
static const int value = sizeof(f(T()));
};
struct B
{
};
struct D : B
{
};
char f(B);
// instantiates A<D>, unqualified name lookup finds f(B) via ADL
static_assert(A<D>::value == sizeof(f(B())), ""); // passes
long f(D); // but wait, f(D) would be a better match!
// A<D> is already instantiated, f(D) is not found
static_assert(A<D>::value == sizeof(f(B())), ""); // passes
C++11 标准建议上述代码调用未定义的行为:
[temp.dep.candidate]
对于依赖于模板参数的函数调用,使用通常的查找规则找到候选函数,除了:
- 对于使用非限定名查找或限定名查找的查找部分,仅找到来自模板定义上下文的函数声明。
- 对于使用关联名称空间的查找部分,仅找到在模板定义上下文或模板实例化上下文中找到的函数声明。
如果函数名称是非限定 ID,并且调用格式错误或找到更好的匹配,则在关联命名空间中的查找考虑所有翻译单元中在这些命名空间中引入的具有外部链接的所有函数声明,而不仅仅是考虑在模板定义和模板实例化上下文中找到的那些声明,则程序具有未定义的行为。
上面的代码是否调用了这个特定的未定义行为?是否可以期望高质量的实施报告警告?