Подтвердить что ты не робот

Нет аргументов, зависящих от параметра шаблона

Я пытаюсь сделать следующее:

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

Ответ 1

Для встроенных типов зависимый от аргумента поиск (ADL) не выполняется, поэтому символ ignore должен быть "импортирован" в текущее пространство имен.

Вы можете, например, сделать это; от наиболее предпочтительных до наименее предпочтительных (т.е. для большинства интрузивных и загрязняющих веществ):

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

Сообщение об ошибке появляется таким образом, потому что в шаблонах вы также вводите область зависимых имен и Двухфазный поиск. Имена, которые зависят от параметра шаблона, например

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

просматриваются в фазе 2, которая возникает после создания экземпляра. Имена, которые не зависят от параметров шаблона, например

class Foo {};

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

должно быть разрешимо в первой фазе.

Это разделение помогает авторам шаблонов найти ошибки раньше и найти правильные символы, и это помогает сделать шаблоны более универсальными. Например, в генераторах С# все должно быть разрешимым, что ограничивает их гибкость (поскольку все, что может использоваться общим, должно быть определено). Напротив, некоторые старые компиляторы С++ разрешались только в фазе 2, то есть во время создания экземпляра, что имело некоторые незначительные последствия для поиска и поиска ошибок.

Двухфазная модель С++ сочетает в себе лучшие из нетерпеливой модели (С#) и ленивой модели (некоторые старые компиляторы С++).

Ответ 3

Сообщение об ошибке означает, что не существует определения ignore, которое компилятор может использовать в этой точке. Это точно та же ошибка, что и вы, если вы делаете:

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

... даже если он выглядит совсем по-другому. Обратите внимание, что здесь нет проблемы с ADL, как говорят другие ответы. Причина, по которой сообщение об ошибке настолько запутано, объясняется тем, как обрабатываются шаблоны компилятором.

Шаблоны обрабатываются в два прохода, во время первого прохода все, что не зависит от типа экземпляра, должно быть проверено без выполнения подстановки типа, во время этого прохода должно быть проверено каждое не зависящее имя, и в этом случае компилятор не удалось разрешить ignore с объявлениями, доступными в месте определения шаблона.

Если выражение зависело от аргументов типа к шаблону, его не нужно было бы полностью разрешать в течение первого прохода, и оно было бы проверено снова после подстановки типа, причем объявления были доступны в месте создания экземпляра.

Ответ 4

У меня была такая же проблема, и я исправил ее, изменив порядок включения.

Как сообщает phresnel, компилятор не может разрешить это на первом этапе, что в моем случае было потому, что заголовок с методом проблемных шаблонов был включен до того, который был с внутренним методом, который не мог быть разрешен.

Добавление необходимого заголовка включает удаление ошибки для меня. Надеюсь, это поможет кому-то еще.

Ответ 5

Это означает, что ignore не может быть найден компилятором, и ADL не может нажать. Это означает, что нет подходящей функции ignore.

Ответ 6

Я не знаю о погоде, когда ваша проблема решена или нет, и я надеюсь, что это будет.

Всякий раз, когда мне приходится сталкиваться с проблемой "Нет аргументов, которые зависят от параметра шаблона" . Я переопределяю метод и вызываю функцию-член родительского класса.

Чтобы показать, что я имею в виду, рассмотрим класс, ниже которого является класс класса 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(){}
};

После компиляции вы получите ошибку, например "Нет аргументов, которые зависят от параметра шаблона" для методов 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(){}
};