没有依赖于模板参数的参数

我正在尝试做以下事情:

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 ===|
110779 次浏览

这意味着编译器无法找到 ignore,ADL 也无法发挥作用。这意味着没有适当范围的 ignore函数。

对于内置类型,不执行 argument dependent lookup (ADL),因此,必须将 ignore符号“导入”到当前命名空间中。

例如,你可以这样做; 从最喜欢的到最不喜欢的(也就是说,从最具侵入性和名称污染) :

  • foobar::ignore (...)
  • using foobar::ignore; ignore(...);
  • using namespace foobar; ignore(...);

出现错误消息是这样的,因为在模板中,您还要进入依赖名称和 两阶段查找的领域。依赖于模板参数的名称,例如。

template <typename T> void foo() {
T x;
x.frobnicate();
}

不依赖于模板参数的名称,如

class Foo {};


template <typename T> void foo() {
Foo foo;
foo.frobnicate();
}

must be resolvable in the first phase.

这种分离有助于模板作者更早地发现 bug 并找到正确的符号,并且有助于使模板更通用。例如,在 C # 泛型中,所有东西都必须是可解析的,这对它们的灵活性施加了相当严格的限制(因为泛型 必须的使用的所有 都是定义的)。相反,一些旧的 C + + 编译器只在第2阶段解析,即在实例化时解析,这对查找和错误发现有一些微妙的影响。

C + + 2阶段模型结合了最好的渴望模型(C #)和延迟模型(一些旧的 C + + 编译器)。

错误消息意味着此时编译器无法使用 ignore的定义。如果你这样做,你会得到完全相同的错误:

void f() {
g();
}
void g() {}

即使看起来不一样。注意,正如其他答案所说,这里没有 ADL 问题。错误消息如此复杂的原因是编译器处理模板的方式。

Templates are processed in two passes, during the first pass everything that is not dependent on the instantiating type must be verified 而不执行类型替换, during this pass every non-dependent name must be checked, and in this case the compiler has failed to resolve ignore with the declarations available at the place of definition of the template.

如果表达式依赖于模板的类型参数,那么在第一次传递过程中就不需要完全解析它,而是再次尝试 之后类型替换,并在实例化的位置提供声明。

有更简单的答案,请参阅 Https://web.archive.org/web/20130423054841/http://www.agapow.net/programming/cpp/no-arguments-that-depend-on-a-template-parameter

DR: 用 this-> 忽略()替换忽略() ,您的问题就会消失。

我也遇到过同样的问题,我通过改变包含顺序来解决它。

正如 phresnel 所说,编译器无法在第一阶段解决这个问题,在我的例子中,这是因为带有有问题的模板方法的头部被包含在带有无法解决的内部方法的头部之前。

添加所需的标题包括为我删除了错误。希望这对其他人有所帮助。

我不知道天气如何,你的问题是否得到解决,我希望它会得到解决。

每当我遇到 “没有依赖于模板参数的参数”的问题时,我就重写该方法并调用父类成员函数。

To show what I mean consider a class below which is template class ADT

template <typename DataTypeOfNode>
class LinearList
{
public:
LinearList(){}
void addAtBeg(DataTypeOfNode data) {
//Inside implementation....
}
DataTypeOfNode removeFromFront() {
//Inside implementation....
}


// And many more useful methods
~LinearList(){}


};

现在,如果你继承了这个带基类的类,像这样说 “优先队列”

template <typename DataTypeOfNode>
class PriorityQueue : public LinearList<DataTypeOfNode>
{
public:


void enqueue(DataTypeOfNode data){
addAtBeg(data);
}


DataTypeOfNode dequeue(){
return removeFromFront() ;
}
PriorityQueue(){}
~PriorityQueue(){}
};

在编译之后,对于 removeFromFront()addAtBeg()方法,您将得到类似于 “没有依赖于模板参数的参数”的错误,因为它们具有模板参数。

要修复此错误,您只需重写这些方法并调用父类方法,如下所示

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(){}
};