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

8hhllhi2  于 11个月前  发布在  其他
关注(0)|答案(6)|浏览(96)

我正在努力做到以下几点:

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 ===|

3pmvbmvn

3pmvbmvn1#

有关更简单的答案,请参见https://web.archive.org/web/20130423054841/http://www.agapow.net/programming/cpp/no-arguments-that-depend-on-a-template-parameter
TL;DR:用this->ignore()替换ignore(),你的问题就会消失。

bxgwgixi

bxgwgixi2#

对于内建类型,不执行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();
}

字符串
在第二阶段,也就是示例化阶段查找。不依赖于模板参数的名称,如

class Foo {};

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


必须在第一阶段解决。
这种分离有助于模板作者更早地发现错误并找到正确的符号,并且有助于使模板更加通用。(因为所有可能被泛型使用的东西都必须被定义)。但是,一些旧的C编译器只在第二阶段解决,即在示例化时,这对查找和错误查找有一些微妙的影响。
C
2阶段模型结合了eager-model(C#)和lazy-model(一些旧的C++编译器)的优点。

bwitn5fc

bwitn5fc3#

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

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

字符串
.即使它看起来 * 非常 * 不同。请注意,这里没有ADL问题,因为其他答案说。错误消息如此复杂的原因是因为编译器处理模板的方式。
模板分两次处理,在第一次处理中,所有不依赖于示例化类型的东西都必须被验证 *,而不执行类型替换 *,在这一次处理中,每个不依赖的名字都必须被检查,在这种情况下,编译器无法用模板定义处的声明解析ignore
如果表达式依赖于模板的类型参数,则在第一次传递时不需要完全解析,并且会在类型替换 * 之后再次尝试,声明在示例化的地方可用。

bbmckpt7

bbmckpt74#

我也遇到了同样的问题,我已经通过改变包含顺序来解决了这个问题。
正如phresnel所说,编译器无法在第一阶段解决这个问题,在我的情况下,这是因为带有有问题的模板方法的头被包含在带有无法解决的内部方法的头之前。
添加所需的标题包括删除了我的错误。希望这对其他人有帮助。

jdzmm42g

jdzmm42g5#

我不知道你的问题是否解决了,我希望它会解决。
每当我遇到**“没有依赖于模板参数的参数”**的问题时,我都会覆盖该方法并调用父类成员函数。
为了说明我的意思,考虑下面的一个类,它是模板类ADT

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

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

};

字符串
现在,如果你用基类继承这个类,比如说**“PriorityQueue”**,就像这样

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

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

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


编译后,你会得到类似**“There are no arguments that depend on a template parameter”**的错误,因为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(){}
};

xmjla07d

xmjla07d6#

这意味着ignore不能被编译器找到,ADL不能启动。这意味着没有合适的作用域ignore函数。

相关问题