簡體   English   中英

std :: find()向后轉C風格的數組?

[英]std::find() backwards on C-style array?

說我需要使用s

typedef struct tagSOMESTRUCT   // Defined by someone else; C-compatible
{
    int count;
    int elements[256];
} SOMESTRUCT;

SOMESTRUCT s;

並說我有一個像以下的功能:

template<typename RevFwdIt>
std::pair<RevFwdIt, RevFwdIt> some_slice_rev(RevFwdIt rbegin, RevFwdIt rend)
{
    RevFwdIt it = basename_rev(rbegin, rend);
    RevFwdIt e = std::find(rbegin, it, 5);
    return std::make_pair(e == it ? rbegin : e, it);
}

為了使用這個功能,我需要說

some_slice_rev(&s.elements[s.count - 1], &s.elements[-1]);

哪個(恕我直言)由於一個一個錯誤而變得丑陋且容易出錯。

一方面,我不能簡單地將some_slice_rev改為some_slice來使用(好多了)

some_slice(&s.elements[0], &s.elements[s.count]);

因為那時std::find會從頭開始搜索而不是結束。

另一方面,代碼本身看起來已經破碎了,因為我無法看到std::find如何處理作為原始指針的“反向迭代器”。

在這種情況下修復代碼的最佳方法是什么? 有沒有辦法使用作為原始指針的反向迭代器? 或者是否有一個標准的重構機制來解決這個問題, 不是改變SOMESTRUCT

我不太確定我理解這個問題(這可能來自你似乎試圖避免的迭代器方向的尷尬混合),但我只是將你的注意力轉向std::reverse_iterator

#include <iostream>
#include <iterator>

// for example
template <typename Iter>
void print_it(Iter first, Iter last)
{
    std::cout << '|';

    for (; first != last; ++first)
        std::cout << ' ' << *first << " |";

    std::cout << std::endl;
}

int main()
{
    int arr[10] = {1, 2, 3, 4};

    int *begin = arr, *end = arr + 4;

    print_it(begin, end);
    print_it(std::reverse_iterator<int*>(end),
                std::reverse_iterator<int*>(begin));
}

它們像雙向迭代器一樣工作,除了++是內部的--反之亦然。

請注意,它有點難看。 您可能需要一些實用功能:

#include <iostream>
#include <iterator>

// for example
template <typename Iter>
void print_it(Iter first, Iter last)
{
    std::cout << '|';

    for (; first != last; ++first)
        std::cout << ' ' << *first << " |";

    std::cout << std::endl;
}

template <typename Iter>
std::reverse_iterator<Iter> make_reverse_iterator(Iter iter)
{
    return std::reverse_iterator<Iter>(iter);
}

int main()
{
    int arr[10] = {1, 2, 3, 4};

    int *begin = arr, *end = arr + 4;

    print_it(begin, end);
    print_it(make_reverse_iterator(end),
                make_reverse_iterator(begin));
}

所以我想你想要這個:

template<typename ForwardIterator >
std::pair<ForwardIterator, ForwardIterator>
    some_slice(ForwardIterator begin, ForwardIterator end)
{
    typedef std::reverse_iterator<ForwardIterator> rev_iter;

    rev_iter it = basename(rev_iter(end), rev_iter(begin));
    rev_iter e = std::find(rev_iter(end), it, 5);

    return std::make_pair(it.base(), e.base());
}

現在相對偏離主題,但請注意,如果s.count256 ,則s.elements[s.count]是未定義的行為,因為s.elements[s.count]*(s.elements + s.count) ,這是要取消引用的有效數組元素。

在實踐中,完整的表達式很好,因為&*x取消了x ,但你仍然可能想要避免它:

some_slice(s.elements, s.elements + s.count);

s.elements[-1]也可能是未定義的行為,但我認為嚴格來說它可能是合法的,因為你在數組之前有一個int成員。

一個簡單的解決方案是編寫一個包裝器迭代器類來模擬反向迭代器,然后使用它而不是原始數組迭代器,像往常一樣使用std::find 所以當std::find調用++it ,它會調用operator++ ,它會在內部遞減實際的迭代器--rawIt 這就是其他標准反向迭代器所做的事情。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM