我正在尝试执行以下操作:
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;
}
我必须从文件中读取所有内容。每个字段由'\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 ===|
答案 0 :(得分:46)
对于内置类型,不执行argument dependent lookup (ADL),因此,ignore
符号必须“导入”到当前名称空间。
例如,你可以这样做;从最优选到最不优选(即最具侵入性和名称污染):
foobar::ignore (...)
using foobar::ignore; ignore(...);
using namespace foobar; ignore(...);
错误消息是这样出现的,因为在模板中,您还可以输入从属名称域和Two Phase Lookup。依赖于模板参数的名称,例如
template <typename T> void foo() {
T x;
x.frobnicate();
}
在阶段2中查找,这是在实例化时。不依赖于模板参数的名称,例如
class Foo {};
template <typename T> void foo() {
Foo foo;
foo.frobnicate();
}
必须在第一阶段可解决。
这种分离有助于模板作者更早发现错误并找到正确的符号,并有助于使模板更通用。例如,在C#泛型中,所有内容都必须是可解析的,这会对其灵活性施加相当严格的限制(因为可能使用的所有内容必须定义)。相反,一些旧的C ++编译器仅在阶段2中解析,即在实例化时,这对于查找和错误发现具有一些微妙的后果。
C ++ 2阶段模型结合了最好的热切模型(C#)和懒惰模型(一些旧的C ++编译器)。
答案 1 :(得分:34)
TL; DR:用this-&gt; ignore()替换ignore(),你的问题就会消失。
答案 2 :(得分:7)
错误消息表示编译器此时没有ignore
的定义。如果你这样做,那就完全一样了:
void f() {
g();
}
void g() {}
...即使它看起来非常不同。请注意,其他答案说,这里没有ADL问题。错误消息如此错综复杂的原因是由于编译器处理模板的方式。
模板在两次传递中处理,在第一次传递期间,必须验证不依赖于实例化类型的所有内容而不执行类型替换,在此传递期间,必须检查每个非依赖名称,在这种情况下,编译器无法使用模板定义位置提供的声明来解析ignore
。
如果表达式依赖于模板的类型参数,则在第一次传递期间不需要完全解析它,并且在类型替换之后将再次尝试,声明可在实例化的地方。
答案 3 :(得分:3)
我遇到了同样的问题,我通过更改包含顺序修复了它。
正如phresnel所说,编译器无法在第一阶段解决这个问题,在我的情况下,因为带有问题模板方法的标头包含在内部方法无法解析的标头之前。
添加所需的标题包括为我删除了错误。希望这有助于其他人。
答案 4 :(得分:2)
我不知道你的问题解决与否的天气,我希望它会有。
每当我遇到&#34;没有依赖于模板参数的参数&#34; 时,我会覆盖该方法并调用父类成员函数。
要显示我的意思,请考虑下面的类是模板类ADT
template <typename DataTypeOfNode>
class LinearList
{
public:
LinearList(){}
void addAtBeg(DataTypeOfNode data) {
//Inside implementation....
}
DataTypeOfNode removeFromFront() {
//Inside implementation....
}
// And many more useful methods
~LinearList(){}
};
现在,如果你继承了这个基类的类,说&#34; PriorityQueue&#34; 就像这样
template <typename DataTypeOfNode>
class PriorityQueue : public LinearList<DataTypeOfNode>
{
public:
void enqueue(DataTypeOfNode data){
addAtBeg(data);
}
DataTypeOfNode dequeue(){
return removeFromFront() ;
}
PriorityQueue(){}
~PriorityQueue(){}
};
在编译之后,您将收到类似&#34的错误;没有任何参数依赖于removeFromFront()
和addAtBeg()
方法的模板参数&#34; ,因为他们有模板参数。
要修复此错误,您只需要覆盖这些方法并调用像这样的父类方法
template <typename DataTypeOfNode>
class PriorityQueue : public LinearList<DataTypeOfNode>
{
public:
//Calling parent class methods
void addAtBeg(DataTypeOfNode data){
LinearList<DataTypeOfNode>::addAtBeg(data) ;
}
DataTypeOfNode removeFromFront(){
return LinearList<DataTypeOfNode>::removeFromFront() ;
}
void enqueue(DataTypeOfNode data){
addAtBeg(data);
}
DataTypeOfNode dequeue(){
return removeFromFront() ;
}
PriorityQueue(){}
~PriorityQueue(){}
};
答案 5 :(得分:1)
这意味着编译器找不到ignore
,并且ADL无法启动。这意味着没有适当范围的ignore
函数。