Working on an algorithm to look at a STL container of STL strings (or other strings, making it general)
Basically it loops through something like a std::list and returns the length of the longest beginning in common. It’s for processing lists of files, like this:
C:\Windows\System32\Stuff.exe C:\Windows\Things\InHere.txt C:\Windows\Foo\Bar.txt
This should return 11, because “C:\Windows\” is in common.
Never written a templatized function before, and my compiler is complaining. Here’s my code:
Header:
// longestBegin.h -- Longest beginning subsequence solver
template <typename SequenceSequenceT, typename SequenceT, typename T >
size_t longestBegin(InputIterator firstCandidates, InputIterator lastCandidates);
Implementation:
// 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;
}
I have a funny feeling I’m missing something fundamental here……
The compiler bombs with the following error:
error C2998: 'size_t longestBegin' : cannot be a template definition
Any ideas? Thanks!
Billy3
Your parameter names in the
templateline need to include any types of function parameters or return types. This means that you need to mentionInputIteratorin your template parameter list. Try changing your function declaration to:Your next problem is: how does the compiler know what
SequenceTis? The answer is that it’s the result of dereferencing anInputIterator. Iterators that aren’t pointers have a nestedtypedefcalledreference, which is just what you need here. Add this to the start of your function so the compiler knows whatSequenceTis:You could have kept
SequenceTas a template parameter, but then the compiler couldn’t guess what it is from looking at the arguments, and you’d have to call your function by typing e.g.longestBegin<string>(arguments), which isn’t necessary here.Also, you’ll notice that this doesn’t work if
InputIteratoris a pointer — pointers don’t have nested typedefs. So you can use a special struct calledstd::iterator_traitsfrom the<iterator>standard header that can sort out these problems for you:Finally, unless the first string is always the longest, you could end up accessing a string past the end of its array inside the second for loop. You can check the length of the string before you access it:
Also note that the function returns
(size_t)(-1)if there is no common prefix.