2009-05-16 9 views
2

de travail sur un algorithme pour regarder un conteneur STL de chaînes STL (ou d'autres chaînes, ce qui rend général)Modèles et syntaxe

Fondamentalement, il boucle à travers quelque chose comme une std :: liste et renvoie la longueur de la plus longue commençant en commun. Il est pour le traitement des listes de fichiers, comme ceci:

 
C:\Windows\System32\Stuff.exe 
C:\Windows\Things\InHere.txt 
C:\Windows\Foo\Bar.txt 

Cela devrait retourner 11, parce que « C:\Windows\ » est en commun.

N'a jamais écrit de fonction matricielle auparavant, et mon compilateur se plaint. Voici mon code:
tête:

// longestBegin.h -- Longest beginning subsequence solver 
template <typename SequenceSequenceT, typename SequenceT, typename T > 
size_t longestBegin(InputIterator firstCandidates, InputIterator lastCandidates); 

Mise en œuvre:

// longestBegin.cpp -- Longest beginning subsequence solver 
#include <stdafx.h> 

template <typename SequenceSequenceT, typename SequenceT, typename T > 
size_t longestBegin(InputIterator firstCandidates, InputIterator lastCandidates) 
{ 
    SequenceT firstString = *firstCandidates; 
    size_t longestValue = firstString.length(); 
    firstCandidates++; 
    for(size_t idx = 0; idx < longestValue; idx++) 
    { 
     T curChar = firstString[idx]; 
     for(InputIterator curCandidate = firstCandidates;curCandidate != lastCandidates; curCandidate++) 
     { 
      if ((*curCandidate)[idx] != curChar) 
       return idx - 1; 
     } 
    } 
    return longestValue; 
} 

J'ai un drôle de sentiment que je manque quelque chose de fondamental ici ......

Le les bombes du compilateur avec l'erreur suivante:

error C2998: 'size_t longestBegin' : cannot be a template definition 

Des idées? Merci!

Billy3

+2

s'il vous plaît augmenter la lisibilité de votre code ici en supprimant les messages de copyright –

+0

Et indiquer dans votre code où vous obtenez le message d'erreur –

+1

D'accord, mais simplement en copiant le commentaire de celui ci-dessus ne vous aide pas. –

Répondre

5

Les noms de vos paramètres dans la ligne template doivent inclure tous les types de paramètres de fonction ou types de retour. Cela signifie que vous devez mentionner InputIterator dans votre liste de paramètres de modèle. Essayez de changer votre déclaration de fonction:


template <typename InputIterator> 
size_t longestBegin(InputIterator firstCandidates, InputIterator lastCandidates) 

Votre problème suivant: comment le compilateur sait ce que SequenceT est? La réponse est que c'est le résultat du déréférencement d'un InputIterator. Les itérateurs qui ne sont pas des pointeurs ont un typedef imbriqué appelé reference, ce qui correspond exactement à ce dont vous avez besoin ici. Ajouter ceci au début de votre fonction de sorte que le compilateur sait ce SequenceT est:


template <typename InputIterator> 
size_t longestBegin(InputIterator firstCandidates, InputIterator lastCandidates) 
{ 
    typedef typename InputIterator::reference SequenceT; 
[etc.] 

Vous auriez pu garder SequenceT comme paramètre de modèle, mais le compilateur ne pouvait pas deviner ce qu'il est de regarder les arguments, et vous devez appeler votre fonction en tapant par exemple longestBegin<string>(arguments), ce qui n'est pas nécessaire ici.

En outre, vous remarquerez que cela ne fonctionne pas si InputIterator est un pointeur - les pointeurs n'ont pas de typedefs imbriqués.Ainsi, vous pouvez utiliser un struct spécial appelé std::iterator_traits de la <iterator>-tête standard qui peut régler ces problèmes pour vous:


//(At the top of your file) 
#include <iterator> 

template <typename InputIterator> 
size_t longestBegin(InputIterator firstCandidates, InputIterator lastCandidates) 
{ 
    typedef typename std::iterator_traits<InputIterator>::reference SequenceT; 
[etc.] 

Enfin, à moins que la première chaîne est toujours la plus longue, vous pourriez finir par accéder à une chaîne au-delà de la fin de son tableau à l'intérieur de la seconde boucle. Vous pouvez vérifier la longueur de la chaîne avant d'y accéder:


//(At the top of your file) 
#include <iterator> 

template <typename InputIterator> 
size_t longestBegin(InputIterator firstCandidates, InputIterator lastCandidates) 
{ 
    typedef typename std::iterator_traits<InputIterator>::reference SequenceT; 
    SequenceT firstString = *firstCandidates; 
    size_t longestValue = firstString.length(); 
    firstCandidates++; 
    for(size_t idx = 0; idx < longestValue; idx++) 
    { 
     T curChar = firstString[idx]; 
     for(InputIterator curCandidate = firstCandidates;curCandidate != lastCandidates; curCandidate++) 
     { 
       if (curCandidate->size() >= idx || (*curCandidate)[idx] != curChar) 
         return idx - 1; 
     } 
    } 
    return longestValue; 
} 

Notez également que la fonction retourne (size_t)(-1) s'il n'y a pas de préfixe commun.

+0

Ouais ... il y a des problèmes avec la logique de ce code ... il a été giflé ensemble pour voir comment la syntaxe fonctionnait. Merci cependant :) –

+0

Coche pour la réponse la plus complète. Je vous remercie! –

+0

@Doug: Je crois que votre réponse manque certaines lignes, la liste des modèles de déclaration est incomplète. Je suppose que ça vous intéresse de savoir ça, n'est-ce pas? ;-) –

2

Vous ne pouvez pas déclarer avant des modèles, je crois. Essayez de déplacer l'implémentation dans le fichier d'en-tête.

1

Il semblerait que vous deviez d'abord mettre l'implémentation dans le fichier d'en-tête car il s'agit d'une fonction modèle et seulement "implémentée" au moment de la compilation.

+0

Ne déchirant pas votre réponse. Cependant "cuisine" était plus rapide;) –

1

InputIterator n'est pas un type que je pense. Pouvez-vous déclarer

InputIterator x; 

dans votre code ou si vous obtenez une erreur?

+0

C'est vrai, mais pas la cause de l'échec que je suis en train de questionner. –