你如何在C风格的数组上使用find_if和reverse_iterator?

问题描述:

要搜索一个元件第一次出现的在C-阵列与POD元件,一个易于可以与std::find_if(begin, end, findit)做到这一点。但我需要最后的发生。 This answer给了我这个想法,这可以用std::reverse_iterator完成。因此,我想:你如何在C风格的数组上使用find_if和reverse_iterator?

std::find_if(std::reverse_iterator<podtype*>(end), 
      std::reverse_iterator<podtype*>(begin), 
      findit); 

这给我的错误:

cannot convert 'std::reverse_iterator< xyz* > ' to 'xyz*' in assignment

你有一个想法如何做这种方式或者你知道一个更好的解决方案?

这是代码:

#include <iostream> 
#include <iterator> 
#include <algorithm> 

struct xyz { 
    int a; 
    int b; 
}; 

bool findit(const xyz& a) { 
    return (a.a == 2 && a.b == 3); 
} 

int main() { 
    xyz begin[] = { {1, 2}, {2, 3}, {2, 3}, {3, 5} }; 
    xyz* end = begin + 4; 

    // Forward find 
    xyz* found = std::find_if(begin, end, findit); 
    if (found != end) 
     std::cout << "Found at position " 
        << found - begin 
        << std::endl; 

    // Reverse find 
    found = std::find_if(std::reverse_iterator<xyz*>(end), 
         std::reverse_iterator<xyz*>(begin), 
         findit); 
    if (found != std::reverse_iterator<xyz*>(end)); 
     std::cout << "Found at position " 
        << found - std::reverse_iterator<xyz*>(end) 
        << std::endl; 

    return 0; 
} 

compiler error on codepad.org

std::find_if函数具有一个返回类型等于传递作为参数的迭代器的类型。在你的情况下,由于你传递的是std::reverse_iterator<xyz*> s作为参数,返回类型将是std::reverse_iterator<xyz*>。这意味着,

found = std::find_if(std::reverse_iterator<xyz*>(end), 
        std::reverse_iterator<xyz*>(begin), 
        findit); 

不会编译,因为foundxyz*

为了解决这个问题,你可以试试这个:

std::reverse_iterator<xyz*> 
rfound = std::find_if(std::reverse_iterator<xyz*>(end), 
         std::reverse_iterator<xyz*>(begin), 
         findit); 

这将解决编译错误。但是,我认为,在这条线,你两个次级错误:

if (found != std::reverse_iterator<xyz*>(end)); 

首先,请注意,你有if语句后一个分号,所以if语句体将被评估不管条件是否为真。

其次,注意std::find_if返回第二个迭代器作为前哨,如果没有谓语一致。因此,这个测试应该是

if (rfound != std::reverse_iterator<xyz*>(begin)) 

因为find_if将返回std::reverse_iterator<xyz*>(begin)如果没有找到的元素。

希望这有助于!

+0

是的,这有助于,谢谢。在两种情况下,返回的索引现在都是1,这看起来是正确的,但如果反向查找的结果会给出索引2,那么返回索引将会很好。我不能从'rfound'中减去'begin',因为这会导致与以前相同的错误。 –

+0

@ ChristianAmmer-我认为这是因为你的逻辑得到索引是错误的。你的减法计算从反向迭代器到数组最后一个元素的距离,它给出了距离数组后部*的距离*,而不是距离前面的距离。 – templatetypedef

+0

我想我现在明白了。逻辑错了,但用'(end - begin) - (rfound - std :: reverse_iterator (end)) - 1'我得到正确的索引。 –