Nat*_*ica 5
GCC 在这里实际上是正确的。如果我们遵循[class.member.lookup]中的规则,我们首先有
C 中 N 的查找集,称为 S(N,C),由两个组件集组成:声明集,一组名为 N 的成员;和子对象集,一组子对象,其中找到了这些成员的声明(可能通过 using-declarations)。在声明集中,类型声明(包括注入的类名)被它们指定的类型替换。S(N,C) 计算如下:
所以我们要为类建立一组名称 S(N, C)(在本例中也称为 C)
继续我们的下一段
如果 P 在 C 的完整类上下文中,则声明集是在 C 的范围内从 C 的类说明符之后立即搜索 N 的结果,否则从 P 搜索。如果结果声明集不为空,则子对象集包含 C 本身,计算完成。
当我们查找operator()
in 时C
,我们没有找到任何东西,所以S(N, C)
是空的。然后我们继续下一段
否则(即,C 不包含 N 的声明或结果声明集为空),S(N,C) 最初为空。计算每个直接非依赖([temp.dep.type])基类子对象Bi中N的查找集,并将每个这样的查找集S(N,Bi)依次合并为S(N,C)。
因此,我们将遍历每个基础并添加它的查找集S(N, C)
,这将我们带到下一个子段
否则,如果 S(N,Bi) 和 S(N,C) 的声明集不同,则合并是不明确的:新的 S(N,C) 是具有无效声明集和子对象并集的查找集套。在随后的合并中,无效的声明集被认为与其他任何不同。
所以,既然没有operator()
in C
,但它在基类中,那么我们现在有包含基类operator()
的无效声明集。然后我们有
搜索的结果是 S(N,T) 的声明集。如果它是无效集合,则程序是非良构的。如果它与从 T 的类说明符之后立即在 T 中搜索 N 的结果不同,则程序是非良构的,不需要诊断。
这告诉我们无效的声明集是格式错误的,因此它是一个错误并且应该无法编译。
解决方法是使用 using 语句将基类函数带入派生类范围
struct C : A, B {
using A::operator();
using B::operator();
};
现在将名称带入C
其中将为您提供一个有效的名称集,然后可以将其传递给重载决议,以便它选择正确的重载。
更多推荐
不正确,不完整,GCC,std,invocable
发布评论