CPPreference提到"在确定命名空间与类的关联集合后,为了进一步的 ADL 处理,忽略此集中所有在类中找到的声明,但不包括命名空间作用域的友元函数及函数模板,在后述点 2 陈述。",如何理解在类中找到的声明?能否
时间: 2024-04-06 13:31:31 浏览: 110
理解为在类的定义中出现的声明,例如在类中声明的成员函数、成员变量、嵌套类型等。根据C++标准,当进行ADL(Argument-dependent lookup)查找时,编译器会忽略在类定义中出现的声明,只在类外部进行查找。这是因为在类内部声明的实体不属于命名空间作用域,而ADL只会在命名空间作用域内进行查找。但是,如果在类内部声明的实体是一个友元函数或函数模板,则可以参与ADL查找。
相关问题
CPPReference中ADL提到// a) 为各类型模板形参提供的所有模板实参的类型(跳过非类型模板形参和模板模板形参) // b) 以任何模板模板实参为其中成员的命名空间 // c) 以任何模板模板实参为其中成员的类(如果它们是类成员模板)是否能根据每一项(a,b,c)都做出解释,并给出示例代码
ADL(Argument-Dependent Lookup)是一种C++中的名字查找机制,它按照一定的规则在一些特定的命名空间中查找函数或者运算符的重载版本。根据C++标准,ADL会考虑以下三个方面:
a) 为各类型模板形参提供的所有模板实参的类型(跳过非类型模板形参和模板模板形参)。
这个方面指的是,在函数模板的定义中,如果使用了某个类型模板参数,那么在调用这个函数时,编译器会查找与这个类型相关的命名空间,来查找对应的函数重载版本。比如:
```cpp
template<typename T>
void foo(T t)
{
bar(t);
}
int main()
{
std::string s = "hello";
foo(s); // ADL会在std命名空间中查找bar的重载版本
}
```
b) 以任何模板模板实参为其中成员的命名空间。
这个方面指的是,在函数模板的定义中,如果使用了某个模板参数,而这个模板参数本身是一个类模板,并且这个类模板中定义了某个命名空间,那么在调用这个函数时,编译器会查找这个命名空间中是否有对应的函数重载版本。比如:
```cpp
template<template<typename> class Container>
void foo(Container<int>& c)
{
using namespace myns; // myns是一个命名空间,是Container<int>的成员
bar(c);
}
int main()
{
std::vector<int> v;
foo(v); // ADL会在myns命名空间中查找bar的重载版本
}
```
c) 以任何模板模板实参为其中成员的类(如果它们是类成员模板)。
这个方面指的是,在类模板中,如果定义了某个类成员模板,并且这个类成员模板中定义了某个命名空间,那么在调用这个类成员模板时,编译器会查找这个命名空间中是否有对应的函数重载版本。比如:
```cpp
template<typename T>
struct S
{
template<typename U>
void foo(U u)
{
using namespace myns; // myns是一个命名空间,是S<T>::foo的成员
bar(u);
}
};
int main()
{
S<int> s;
std::string str = "hello";
s.foo(str); // ADL会在myns命名空间中查找bar的重载版本
}
```
需要注意的是,ADL只会在函数模板的定义所在的命名空间和上述三个方面中的命名空间中查找函数或者运算符的重载版本,而不会在函数模板的调用点所在的命名空间中查找。因此,如果想要让ADL在某个特定的命名空间中查找函数或者运算符的重载版本,可以使用using声明或using指令将该命名空间引入到函数模板的定义所在的作用域。
阅读全文