2

特定のファイル形式を読み取るライブラリを作成しています。ファイルは、メモリ マップ ファイル (boost::interprocessテンプレート) で読み取られています。これらのファイルでは、std::regex. 不必要なコピーを避けるために、メモリ マップ ファイルを (C スタイルの char 配列として) 直接使用したいと考えています。

しばらく調査した後、次の2つのアプローチを思い付きました。

  • オブジェクトのpubsetbufメソッドを使用するstreambuf
  • char*ポインターを反復子として使用する

しかし、最初の実装は STL ベンダーにとってオプションであるため、私は 2 番目のアプローチにこだわっています。のコンストラクターstd::string::iteratorはプライベートとして宣言されているため、イテレーターの実装全体もベンダー固有のようです。私は自分のイテレータを書きました:

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メソッド (または他の char 関連の 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
}

ありがとう

4

1 に答える 1

3

の定義std::smatchは の特殊化ですstd::match_results。この特殊化はstring::const_iterator、 に渡されるテンプレート引数の反復子型として を使用しますstd::match_results。これには、渡される begin 引数と end 引数std::regex_searchも type である必要がありますstring::const_iterator

C++ では、ポインターは双方向反復子の要件を満たし、反復子クラスでそれらをラップする必要はありません。charポインターが指すバッファーを検索する必要がある場合は、反復子の型を明示的に使用するstd::cmatchか、使用して指定することができます。std::match_results次の 2 つの例では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

于 2013-06-02T21:00:31.833 に答える