依赖模板的基成员没有正确解析
Template dependent base member is not resolved properly
这个问题是将成员函数从基类移到派生类没有明显原因地破坏程序(这是为什么不应该使用using namespace std;
的一个主要例子)
,其中答案建议通过this->
限定依赖模板名称(这确实是引用此类依赖成员时的方法)。但是,似乎有一个问题,所以我将列出一个重现该问题的最小示例。
考虑以下代码:
#include <iostream>
#include <bitset>
using namespace std;
template<class T>
struct B
{
T bitset{};
};
template<class T>
struct D : B<T>
{
bool foo()
{
return this->bitset < 32;
}
};
int main(){}
Live on Coliru
令人费解的是,即使this->bitset
应该引用成员B<T>::bitset
,编译器仍然混淆,认为我们试图引用std::bitset<std::size_t>
。这个错误出现在gcc6和clang3.7上。知道为什么会这样吗?但是用B<T>::bitset
限定它是可以的。
In member function 'bool D<T>::foo(T, std::__cxx11::string)': cpp/scratch/minimal.cpp:24:22: error: invalid use of 'class std::bitset<1ul>'
编辑
在我看来,这像是一个解析/名称查找错误。如果我们用任何其他比较运算符替换<
(感谢@Leon的注释),例如
return this->bitset == 32;
程序编译。所以我猜在this->bitset < 32
中,解析器认为我们正在尝试实例化一个模板(<
符号),而我们忘记关闭>
。但是我也不知道这到底是一个bug还是语言应该是这样工作的
tl;dr看起来这是一个深思熟虑的决定,特别是为了支持您已经使用的替代语法。
下列标准的大致演练:
this-> B <
^
- 可以是模板id的开头,也可以是小于,所以让我们检查一下!
-
this->B
确实命名了一些东西,但它是一个模板B<T>
,所以继续 -
B
本身也命名了一些东西,一个类模板B<T>
等等,它们是一样的!这意味着我们使用
this->B<T>
作为限定符,它毕竟不是小于 -
另一种情况下,
this->bitset
以相同的方式执行,直到第三步,当它意识到有两个不同的东西叫做bitset
(一个模板类成员和一个类模板)时,就放弃了。
这是我的工作草案,所以不一定是最近的,但是:
3.4.5类成员访问[basic.lookup]。classref]
的上下文中查找
1
在类成员访问表达式(5.2.5)中,表示或者-> token是立即在标识符后面加上<</em>,标识符必须是查找以确定是否有<是模板的开头吗实参列表(14.2)或小于操作符。标识符是第一位的在类中查找对象表达式。如果标识符为没有找到,则在整个上下文中查找后缀表达式和应该命名一个类模板。>如果查找在对象表达式的类找到模板,其名称也为在整个后缀表达式和
- 如果没有找到该名称,则使用对象表达式类中找到的名称,否则
- 如果该名称在整个后缀表达式的上下文中找到,并且没有命名类模板,使用对象表达式类中找到的名称,否则
- 如果找到的名字是一个类模板,它应该和在类中找到的名字指向同一个实体对象表达式,否则程序是病态的。
因此,在任何像this->id < ...
这样的表达式中,它必须处理id<...
是模板标识符的开始(如this->B<T>::bitset
)的情况。
它仍然首先检查对象,但如果this->id
找到模板,则应用进一步的步骤。在您的例子中,this->bitset
可能被认为是一个模板,因为它仍然依赖于T
,所以它发现冲突的std::bitset
并在上面的第三个项目中失败。
- 如何添加依赖于类本身的模板成员变量
- 初始化依赖于子类的继承类的常量类成员
- 类成员函数参数列表是否可以依赖于模板参数?
- 依赖于类成员属性的类实例成员
- 类成员和依赖项注入的对象与引用
- 依赖注入:依赖关系需求字段/成员
- 依赖模板基础的受保护成员
- 单独库中的类成员函数定义和链接依赖项
- 依赖于依赖类型的非静态数据成员的非限定名称
- 如何让成员函数实现依赖于类的模板参数?
- 具有依赖于实现的成员函数类型的多个静态接口
- 初始化依赖于另一个类成员的类成员
- 如何处理相互依赖并具有模板成员的类
- 模板成员中的循环类依赖项
- 如何模拟依赖的成员变量
- 无法定义依赖类型定义的成员
- 如何强制依赖静态对象(包括模板成员)的初始化顺序
- 在多继承编译器的情况下访问成员变量是否依赖?如何正确地做
- 如何从 std::array<T, N>::p ointer 成员/依赖类型推断数组大小?
- 初始化C/ c++结构体的const成员…依赖于编译器的