我正在尝试执行以下操作:
template <class T>
std::ifstream& operator>> (std::ifstream& fin, List<T> l)
{
T temp;
l.resize(0);
fin >> ignore(1,'\t');
for(ListIterator<T> i=l.begin();i!=l.end();i++)
{
fin >> ignore(1,'\t') >> temp;
l.push_back(temp);
}
return fin;
}
Run Code Online (Sandbox Code Playgroud)
我必须从文件中读取所有内容.每个字段都按'\t'
字符分隔,因此我必须忽略'\t'
字符.
错误日志如下:
/home/ramy/Documents/C++/Prova/Util.h||In function ‘std::ifstream& Util::operator>> (std::ifstream&, Util::List<T>)’:|
/home/ramy/Documents/C++/Prova/Util.h|431|error: there are no arguments to ‘ignore’ that depend on a template parameter, so a declaration of ‘ignore’ must be available|
/home/ramy/Documents/C++/Prova/Util.h|431|note: (if you use ‘-fpermissive’, G++ will accept your code, but allowing the use of an undeclared name is deprecated)|
||=== Build finished: 1 errors, 0 warnings ===|
Run Code Online (Sandbox Code Playgroud)
Seb*_*ach 47
对于内置类型,不执行参数相关查找(ADL),因此,ignore
必须将符号"导入"到当前名称空间中.
例如,你可以这样做; 从最优选到最不优选(即最具侵入性和名称污染):
foobar::ignore (...)
using foobar::ignore; ignore(...);
using namespace foobar; ignore(...);
错误消息是这样出现的,因为在模板中,您还可以输入从属名称和两阶段查找的领域.依赖于模板参数的名称,例如
template <typename T> void foo() {
T x;
x.frobnicate();
}
Run Code Online (Sandbox Code Playgroud)
在阶段2中查找,这是在实例化时.不依赖于模板参数的名称,例如
class Foo {};
template <typename T> void foo() {
Foo foo;
foo.frobnicate();
}
Run Code Online (Sandbox Code Playgroud)
必须在第一阶段可以解决.
这种分离有助于模板作者更早发现错误并找到正确的符号,这有助于使模板更通用.例如,在C#泛型中,所有内容都必须是可解析的,这会对其灵活性施加相当严格的限制(因为必须定义泛型可能使用的所有内容).相反,一些旧的C++编译器仅在阶段2中解析,即在实例化时,这对于查找和错误发现具有一些微妙的后果.
C++ 2阶段模型结合了最好的eager模型(C#)和懒惰模型(一些旧的C++编译器).
小智 41
TL; DR:用this-> ignore()替换ignore(),你的问题就会消失.
错误消息表示ignore
此时编译器无法使用该定义.如果你这样做,那就是完全相同的错误:
void f() {
g();
}
void g() {}
Run Code Online (Sandbox Code Playgroud)
......即使它看起来非常不同.请注意,其他答案说,这里没有ADL问题.错误消息如此错综复杂的原因是由于编译器处理模板的方式.
模板在两次传递中处理,在第一次传递期间,必须验证不依赖于实例化类型的所有内容而不执行类型替换,在此传递期间必须检查每个非依赖名称,并且在这种情况下编译器未能ignore
使用模板定义位置提供的声明进行解析.
如果表达式依赖于模板的类型参数,则在第一次传递期间不需要完全解析它,并且在类型替换之后将再次尝试它,并且在实例化的地方可以使用声明.
我遇到了同样的问题,我通过更改包含顺序来解决它。
正如 phresnel 所说,编译器无法在第一阶段解决这个问题,在我的情况下,这是因为模板方法有问题的头文件包含在无法解析的内部方法之前。
添加所需的标头包括为我删除了错误。希望这对其他人有帮助。