繁体   English   中英

模板和语法

[英]Templates and Syntax

使用算法查看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

template行中的参数名称需要包含任何类型的函数参数或返回类型。 这意味着您需要在模板参数列表中提及InputIterator 尝试将函数声明更改为:


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

您的下一个问题是:编译器如何知道SequenceT是什么? 答案是它是取消引用InputIterator的结果。 非指针的迭代器有一个名为reference的嵌套typedef ,这正是你需要的。 将其添加到函数的开头,以便编译器知道SequenceT是什么:


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

您可以将SequenceT保留为模板参数,但编译器无法猜测查看参数是什么,您必须通过输入例如longestBegin<string>(arguments)来调用您的函数,这不是'这是必要的。

此外,您会注意到,如果InputIterator是一个指针,这不起作用 - 指针没有嵌套的typedef。 因此,您可以使用来自<iterator>标准头的名为std::iterator_traits的特殊结构,它可以为您解决这些问题:


//(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)

我相信你不能转发声明模板。 尝试将实现移动到头文件中。

看起来您首先需要将实现放入头文件,因为它是一个模板函数,并且只在编译时“实现”。

InputIterator不是我认为的类型。 你能宣布吗?

InputIterator x;

在您的代码中,或者您收到错误?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM