Шаблоны и Синтаксис - PullRequest
2 голосов
/ 16 мая 2009

Работа над алгоритмом для просмотра контейнера STL строк STL (или других строк, делая его общим)

По сути, он проходит через что-то вроде std :: list и возвращает длину самого длинного общего начала. Это для обработки списков файлов, например:

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

Это должно вернуть 11, потому что "C:\Windows\" является общим.

Никогда ранее не писал шаблонизированную функцию, и мой компилятор жалуется. Вот мой код:
Заголовок:

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

Реализация:

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

У меня странное чувство, что я упускаю что-то фундаментальное здесь ......

Компилятор бомбит со следующей ошибкой:

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

Есть идеи? Спасибо!

Billy3

Ответы [ 4 ]

5 голосов
/ 16 мая 2009

Ваши имена параметров в строке template должны включать любые типы параметров функции или возвращаемых типов. Это означает, что вам нужно упомянуть InputIterator в вашем списке параметров шаблона. Попробуйте изменить объявление функции на:


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

Ваша следующая проблема: как компилятор узнает, что такое SequenceT? Ответ в том, что это результат разыменования InputIterator. Итераторы, которые не являются указателями, имеют вложенный typedef с именем reference, который вам здесь нужен. Добавьте это в начало вашей функции, чтобы компилятор знал, что такое SequenceT:


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

Вы могли бы сохранить SequenceT в качестве параметра шаблона, но тогда компилятор не мог угадать, что это такое, глядя на аргументы, и вам пришлось бы вызывать свою функцию, набрав, например, например. longestBegin<string>(arguments), что здесь не обязательно.

Кроме того, вы заметите, что это не работает, если InputIterator является указателем - указатели не имеют вложенных typedefs. Таким образом, вы можете использовать специальную структуру std::iterator_traits из стандартного заголовка <iterator>, которая может решить эти проблемы для вас:


//(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.]

Наконец, если первая строка не всегда самая длинная, вы можете получить доступ к строке после конца ее массива внутри второго цикла for. Вы можете проверить длину строки перед тем, как получить к ней доступ:


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

Также обратите внимание, что функция возвращает (size_t)(-1), если нет общего префикса.

2 голосов
/ 16 мая 2009

Вы не можете пересылать объявления шаблонов, я считаю. Попробуйте переместить реализацию в заголовочный файл.

1 голос
/ 16 мая 2009

InputIterator не тип, я думаю. Можете ли вы объявить

InputIterator x;

в вашем коде или вы получаете ошибку?

1 голос
/ 16 мая 2009

Похоже, вам сначала нужно поместить реализацию в заголовочный файл, поскольку это функция шаблона, и она только "реализована" во время компиляции.

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