gpt4 book ai didi

c++ - 使用 C 风格数组作为 STL 字符串操作的后端

转载 作者:搜寻专家 更新时间:2023-10-31 01:49:10 24 4
gpt4 key购买 nike

我正在编写一个库来读取某些特定的文件格式。正在使用内存映射文件(boost::interprocess 模板)读取该文件。在这些文件上,我必须使用 std::regex 进行一些搜索。为了避免不必要的复制,我想直接使用内存映射文件(作为 C 风格的字符数组)。

经过一段时间的研究,我想出了以下两种方法:

  • 使用 streambuf 对象的 pubsetbuf 方法
  • 使用char*指针作为迭代器

但是由于第一个方法的实现对于 STL 供应商来说是可选的,所以我坚持使用第二种方法。由于 std::string::iterator 的构造函数被声明为私有(private)的,并且整个迭代器实现似乎也是特定于供应商的。我写了我自己的迭代器:

template<typename T>
class PointerIterator: std::iterator<std::input_iterator_tag, T> {
public:
PointerIterator(T* first, std::size_t count): first_(first), last_(first + count) {}
PointerIterator(T* first, T* last): first_(first), last_(last) {}

class iterator {
public:
iterator(T* p): ptr_(p) {}
iterator(const iterator& it): ptr_(it.ptr_) {}
iterator& operator++() {
++ptr_;
return *this;
}
iterator operator++(int) {
iterator temp(*this);
++ptr_;
return temp;
}
bool operator==(const iterator& it) { return ptr_ == it.ptr_; }
bool operator!=(const iterator& it) { return ptr_ != it.ptr_; }
T& operator*() { return *ptr_; }
private:
T* ptr_;
};
iterator begin() {
return iterator(first_);
}
iterator end() {
return iterator(last_);
}
private:
T* first_;
T* last_;
};

迭代器正在工作,但要与 std::regex_search 方法(或其他与字符相关的 STL 方法)一起使用,它必须与 STL 迭代器具有相同的类型。

是否有一些通用方法可以将我的迭代器转换为 STL 迭代器(通过 STL 实现可移植)或使用我没有提到的另一种方法实现整个过程?

编辑:

使用 std::regex_search 的源代码:

std::regex re(...);
boost::interprocess::mapped_region region(...);
char* first = static_cast<char*>(region.get_address());
char* last = first + 5000;

// ...

PointerIterator<char> wrapper(first, last);
std::smatch match;
while (std::regex_search(wrapper.begin(), wrapper.end(), match, re)) { // Error: No matching function call to 'regex_search'
// do something
}

谢谢

最佳答案

std::smatch 的定义是 std::match_results 的特化。此特化使用 string::const_iterator 作为传递给 std::match_results 的模板参数中的迭代器类型。这要求传递给 std::regex_search 的 begin 和 end 参数也属于 string::const_iterator 类型。

在 C++ 中,指针满足双向迭代器的要求,没有必要将它们包装在迭代器类中。如果您需要搜索由 char 指针指向的缓冲区,您可以使用 std::cmatch 或使用 std::match_results 和明确指定迭代器类型。在以下两个示例中,我保留了 PointerIterator 的使用,以提供直接适用于您当前代码库的解决方案。我还提供了一个独立的示例,如果您想要取消使用自定义迭代器类,您可以引用。

PointerIterator<char> wrapper(first, last);
std::cmatch match; // <<--

while (std::regex_search(wrapper.begin(), wrapper.end(), match, re))
{
// do something
}

...改为使用 std::match_results

PointerIterator<char> wrapper(first, last);
std::match_results<const char*> match; // <<--

while (std::regex_search(wrapper.begin(), wrapper.end(), match, re))
{
// do something
}

下面是一个独立的示例,应该提供一些经过整理的说明。它基于 cppreference.com 上的示例并使用 const char* 而不是 std::string 作为搜索目标。

#include <regex>
#include <iostream>
int main()
{
const char *haystack = "Roses are #ff0000";
const int size = strlen(haystack);

std::regex pattern(
"#([a-f0-9]{2})"
"([a-f0-9]{2})"
"([a-f0-9]{2})");

std::cmatch results;

std::regex_search(haystack, haystack + size, results, pattern);

for (size_t i = 0; i < results.size(); ++i) {
std::csub_match sub_match = results[i];
std::string sub_match_str = sub_match.str();
std::cout << i << ": " << sub_match_str << '\n';
}
}

这会产生以下输出。

0: #ff0000
1: ff
2: 00
3: 00

关于c++ - 使用 C 风格数组作为 STL 字符串操作的后端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16886696/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com