web-dev-qa-db-fra.com

Il n'y a pas d'arguments qui dépendent d'un paramètre de modèle

J'essaie de faire ce qui suit:

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;
}

Je dois lire tout le contenu d'un fichier. Chaque champ est séparé par '\t' caractère, je dois donc ignorer le '\t' personnages.

Le journal des erreurs est le suivant:

/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 ===|
58
Ramy Al Zuhouri

Pour les types intégrés, la recherche dépendante de l'argument (ADL) n'est pas effectuée; par conséquent, un symbole ignore doit être "importé" dans l'espace de noms actuel.

Vous pouvez, par exemple, le faire; du plus préféré au moins préféré (c'est-à-dire le plus intrusif et le plus polluant):

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

Le message d'erreur s'affiche comme ceci car dans les modèles, vous entrez également le domaine des noms dépendants et recherche en deux phases . Les noms qui dépendent d’un paramètre de modèle, par exemple.

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

sont recherchées dans la phase 2, qui est sur l'instanciation. Les noms qui ne dépendent pas des paramètres de modèle, tels que

class Foo {};

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

doit pouvoir être résolu dans la première phase.

Cette séparation aide les auteurs de modèles à rechercher les bogues plus tôt et à trouver les symboles corrects, et à rendre les modèles plus génériques. Par exemple, dans les génériques C #, tout doit être résoluble, ce qui limite de manière assez stricte leur flexibilité (car tout ce qui peut être utilisé par un générique doit être défini). À l’opposé, certains anciens compilateurs C++ ne se sont résolus qu’en phase 2, c’est-à-dire au moment de l’instanciation, ce qui a eu des conséquences subtiles sur la recherche et la recherche d’erreurs.

Le modèle à deux phases C++ combine le meilleur du modèle eager (C #) et du modèle paresseux (certains anciens compilateurs C++).

46
Sebastian Mach

Pour une réponse plus facile, voir https://web.archive.org/web/20130423054841/http://www.agapow.net/programming/cpp/no-arguments-that-depend-on-a- template-paramètre

TL; DR: remplacez ignore () par this-> ignore () et votre problème disparaîtra.

37
John Hainsworth

Le message d'erreur signifie qu'il n'y a pas de définition de ignore que le compilateur peut utiliser à ce stade. C'est exactement la même erreur que vous obtenez si vous faites:

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

... même si cela a l'air très différent. Notez qu'il n'y a pas de problème ADL ici comme le disent les autres réponses. La raison pour laquelle le message d'erreur est si compliqué est due à la façon dont les modèles sont traités par le compilateur.

Les modèles sont traités en deux passes: lors de la première étape, tout ce qui n'est pas dépendant du type d'instanciation doit être vérifié sans effectuer la substitution de type, lors de cette passe, chaque nom non dépendant doit être vérifié et Dans ce cas, le compilateur n'a pas réussi à résoudre ignore avec les déclarations disponibles à l'emplacement de la définition du modèle.

Si l'expression dépend des arguments de type du modèle, il ne sera pas nécessaire qu'elle soit entièrement résolue lors de la première passe et une nouvelle tentative sera effectuée après substitution de type, avec les déclarations disponibles sur le lieu de l'instanciation .

J'ai eu le même problème et je l'ai résolu en changeant la commande include.

Comme le dit phresnel, le compilateur ne peut pas résoudre ce problème lors de la 1ère phase, ce qui dans mon cas était dû au fait que l'en-tête avec la méthode du modèle problématique était inclus avant celui avec la méthode interne qui n'a pas pu être résolu.

L'ajout de l'en-tête nécessaire a supprimé l'erreur pour moi. J'espère que ceci aide quelqu'un d'autre.

3

Je ne sais pas si votre problème a été résolu ou non et j'espère que ce sera le cas.

Chaque fois que je fais face au problème de "Il n'y a pas d'arguments qui dépendent d'un paramètre de modèle" J'écrase la méthode et appelle la fonction membre de la classe parent.

Pour montrer ce que je veux dire, considérons une classe ci-dessous qui est la classe de modèle ADT

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

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

};

Maintenant, si vous héritez de cette classe avec une classe de base, dites "PriorityQueue" comme ceci

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

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

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

Après avoir complété, vous obtiendrez une erreur comme "Il n'y a pas d'arguments qui dépendent d'un paramètre de modèle" pour removeFromFront() et addAtBeg() méthodes, car elles ont des paramètres de modèle.

Pour corriger cette erreur, il vous suffit de redéfinir ces méthodes et d'appeler les méthodes de la classe parente comme ceci

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(){}
};
2
Mr. Suryaa Jha

Cela signifie que ignore ne peut pas être trouvé par le compilateur et ADL ne peut pas entrer en jeu. Cela signifie qu'il n'y a pas de fonction ignore convenablement définie.

1
Puppy