std :: find()向后转C风格的数组?

Meh*_*dad 4 c++ pointers iterator find

说我需要使用s:

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

SOMESTRUCT s;
Run Code Online (Sandbox Code Playgroud)

并说我有一个像以下的功能:

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);
}
Run Code Online (Sandbox Code Playgroud)

为了使用这个功能,我需要说

some_slice_rev(&s.elements[s.count - 1], &s.elements[-1]);
Run Code Online (Sandbox Code Playgroud)

哪个(恕我直言)由于一个一个错误而变得丑陋且容易出错.

一方面,我不能简单some_slice_revsome_slice改为使用(好多了)

some_slice(&s.elements[0], &s.elements[s.count]);
Run Code Online (Sandbox Code Playgroud)

因为那时std::find会从头开始而不是结束.

另一方面,代码本身对我来说已经很糟糕了,因为我无法看到如何std::find处理作为原始指针的"反向迭代器".

在这种情况下修复代码的最佳方法是什么?有没有办法使用作为原始指针的反向迭代器?或者是否有一个标准的重构机制来解决这个问题,不是改变SOMESTRUCT

GMa*_*ckG 7

我不太确定我理解这个问题(这可能是你似乎试图避免的迭代器方向的混淆),但我会引起你的注意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));
}
Run Code Online (Sandbox Code Playgroud)

它们像双向迭代器一样工作,除了++在内部--,反之亦然.

请注意,它有点难看.您可能需要一些实用功能:

#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));
}
Run Code Online (Sandbox Code Playgroud)

所以我想你想要这个:

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());
}
Run Code Online (Sandbox Code Playgroud)

相对题外话了,但请注意,s.elements[s.count]是不确定的行为,如果s.count256,由于s.elements[s.count]*(s.elements + s.count),这不是一个有效的数组元素取消引用.

在实践中,完整的表达式很好,因为&*x取消了x,但你仍然可能想避免它:

some_slice(s.elements, s.elements + s.count);
Run Code Online (Sandbox Code Playgroud)

s.elements[-1]也可能是未定义的行为,虽然我认为严格来说它可能是合法的,因为你int在数组之前有一个成员.