依赖型基类
基类依赖模版参数
template <typename T>
class BBB{
public:
void one(int ){}
};
template <typename T>
class DDD : public BBB<T>
{
public:
void f()
{
one(1);
}
};
编译时会有警告:
/home/ubuntu/MyRep/cpp/TestTemplate.cpp:26:4: warning: there are no arguments to ‘one’ that depend on a template parameter, so a declaration of ‘one’ must be available [-fpermissive]
26 | one(1);
| ^~~
/home/ubuntu/MyRep/cpp/TestTemplate.cpp: In instantiation of ‘void DDD<T>::f() [with T = int]’:
/home/ubuntu/MyRep/cpp/TestTemplate.cpp:124:6: required from here
/home/ubuntu/MyRep/cpp/TestTemplate.cpp:26:7: warning: ‘one’ was not declared in this scope, and no declarations were found by argument-dependent lookup at the point of instantiation [-fpermissive]
26 | one(1);
| ~~~^~~
/home/ubuntu/MyRep/cpp/TestTemplate.cpp:26:7: note: declarations in dependent base ‘BBB<int>’ are not found by unqualified lookup
/home/ubuntu/MyRep/cpp/TestTemplate.cpp:26:7: note: use ‘this->one’ instead
one 函数是非依赖名称(可以理解为:没有依赖于模板参数的名称),编译器在看到时就查找,这时 BBB 还没有实例化,(原因2:并且非依赖型名称不会在依赖型基类中查找),先进行普通查找(作用域内),所以找不到 ‘one’ was not declared in this scope one 同时也是非受限名称 (可以理解为: 前面没有 -> :: . ), 普通查找没找到函数,进行ADL查找。ADL 查找会从关联类和关联名字空间查找
ADL 规则, 对于给定的类型, 关联类 和 关联名字空间 所组成的集合的准确定义可以通过下列规则来确定: (1)对于基本类型(int, char等), 该集合为空集 (2)对于指针和数组类型,该集合是所引用类型的关联类和关联名字空间 (3)对于枚举类型,名字空间是名字空间是枚举声明所在的名字空间,对于类成员,关联类是枚举所在的类 (4)对于class(包含联合类型),关联类包括该类本身,他的外围类,直接基类,间接基类。关联名字空间包括每个关联类所在的名字空间。 (5)对于函数类型, 该集合包含所有参数类型和返回类型的关联类和关联名字空间 (6)对于类X的成员指针类型,除了包括成员相关的关联名字空间,关联类,该集合还包括与X相关的关联名字空间和关联类
根据第五条,参数类型int ,返回类型 void, 集合也都是空集,仍然找不到 one 函数,所以 and no declarations were found by argument-dependent lookup at the point of instantiation。 ADL : argument-dependent lookup。
代码改为:
this->one(1);
编译通过, 因为将 one 变成了依赖型名称( 根据依赖型名称定义,如果 -> 左边的表达式类型依赖于模板参数,该受限名称(one)也是依赖型名称),而又根据 C++规则,依赖型名称在实例化时才会进行查找,这是BBB已经被实例化,找到了 one。
|