c++ - 模板的合格和不合格名称查找的不同行为

标签 c++ templates lookup language-lawyer argument-dependent-lookup

这段代码应该如何表现?如果我在 call_read() 函数中使用 qualified 名称,它会调用通用函数而忽略我的重载;如果我使用 unqualified 名称,它首先调用重载,然后调用通用版本。有什么不同?它是 GCC 中的错误吗?

#include <iostream>

struct info1 {};
struct info2 {};

template<class T> void read(T& x)
{
   std::cout << "generic" << std::endl;
}

template<class T> void call_read(T& x)
{
   ::read(x); // if I replace ::read(x) with read(x) the overload is called
}

void read(info1& x)
{
   std::cout << "overload" << std::endl;
}

int main()
{
   info1 x;
   info2 y;
   call_read(x);
   call_read(y);
}

我还注意到它对基本类型的工作方式不同。 请看下面的代码

#include <iostream>

typedef struct info1 {};
typedef struct info2 {};
typedef int info3;
typedef double info4;

template<class T> void read(T x)
{
    std::cout << "generic" << std::endl;
}

template<class T> void call_read(T x)
{
    read(x);
}

void read(info1 x)
{
    std::cout << "overload" << std::endl;
}
void read(info3 x)
{
    std::cout << "overload" << std::endl;
}

int main()
{
    call_read(info1());
    call_read(info2());
    call_read(info3());
    call_read(info4());
}

它应该调用两次重载函数,但事实并非如此。 在这里查看结果 http://codepad.org/iFOOFD52

最佳答案

您所观察的是两阶段名称查找参数相关查找的叠加。

让我们看看标准是怎么说的 (C++03)。 [temp.dep]:

[...] In an expression of the form:

postfix-expression ( expression-listopt )

where the postfix-expression is an identifier, the identifier denotes a dependent name if and only if any of the expressions in the expression-list is a type-dependent expression (14.6.2.2).

这意味着在 read::read 中,read 都是从属名称,因为 x 是类型相关。这意味着它在实例化时已解决。让我们看看这个[temp.dep.candidate]的规则是什么:

For a function call that depends on a template parameter, if the function name is an unqualified-id but not a template-id, the candidate functions are found using the usual lookup rules (3.4.1, 3.4.2) except that:

— For the part of the lookup using unqualified name lookup (3.4.1), only function declarations with external linkage from the template definition context are found.

因此对于 ::read 情况,只考虑在模板定义之前声明的函数。但是:

— For the part of the lookup using associated namespaces (3.4.2), only function declarations with external linkage found in either the template definition context or the template instantiation context are found.

对于不合格的read,两个函数都被考虑,在模板定义和模板实例化时可见。

关于c++ - 模板的合格和不合格名称查找的不同行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8501294/

相关文章:

Mongodb聚合查找查询——返回所有子文档

python - 如何在Python中创建带有负索引/输入的查找表?

使用 data.table 在 R 中重建索引?

c++ - 是否可以用 CMake 将某些符号替换为不同的符号?

c++ - 在具有不同模板参数的列表项上调用参数化方法

c++ - 如何通过引用传递参数给模板类的成员函数?

C++ 可变参数模板 - 限制参数的数量

c++ - 为什么我收到以下错误 : "no match for ' operator= ='" ?(带有模板的嵌套类)

c++ - 数组错误的初始值设定项太多

c++ - 为什么 clang 不产生关于阴影的警告?