【发布时间】:2016-11-07 17:06:33
【问题描述】:
这个问题是后续的
Moving a member function from base class to derived class breaks the program for no obvious reason(这是为什么不应该使用 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(){}
令人困惑的是,即使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 中,解析器认为我们正在尝试实例化一个模板(< 符号),而我们忘记关闭>。但是再次不知道这是否确实是一个错误,或者这就是该语言的工作方式。
【问题讨论】:
-
我认为编译器只是在巧妙地告诉您,您确实应该使用 std::bitset ;) 而不是重新调整用途的整数。
-
可能是因为
name-lookup的工作方式?name-lookup在一个简单的案例中通过检查派生命名空间,然后是基本命名空间,然后是全局范围来工作。因为这里的Base是依赖的,所以它无法查看它的范围并找出它,直到它找到一个实例化。 -
@Arunmu:我希望在数据成员和成员函数的情况下推迟名称查找;这似乎有所不同。
-
@MatthieuM。我认为Arunmu可能是对的。即使
main()为空,我们仍然会收到错误消息。因此错误出现在辅助名称查找之前。我得回josuttis.com/tmplbook看看具体的规则是什么:) -
@Pixelchemist 是的,我知道,你甚至不需要
this->,我一般也不使用using namespace。问题是为什么非限定名称不起作用,因为它看起来是一个非常奇怪的解析问题。