Там нет аргументов, которые зависят от параметра шаблона - PullRequest
58 голосов
/ 30 марта 2012

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

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

Ответы [ 6 ]

47 голосов
/ 30 марта 2012

Для встроенных типов зависимый от аргумента поиск (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();
}

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

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

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

37 голосов
/ 20 марта 2013

Для более простого ответа см. https://web.archive.org/web/20130423054841/http://www.agapow.net/programming/cpp/no-arguments-that-depend-on-a-template-parameter

TL; DR: замените ignore () на this-> ignore (), и ваша проблема исчезнет.

7 голосов
/ 30 марта 2012

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

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

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

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

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

3 голосов
/ 11 августа 2013

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

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

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

2 голосов
/ 03 ноября 2017

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...