如何解决std :: function没有operator ==的事实?

时间:2015-01-28 23:23:22

标签: c++ c++11

问题:如果不能编译,下面的代码将非常具有表现力和简洁性,如果不是很快的话。

它无法编译,因为您无法将std :: function实例与operator ==()进行比较。并且std :: find()试图做到这一点。

当然,我可以采用一种完全不同的实现方式,但是我很顽固,喜欢下面的代码,我正在寻找“尽可能接近”的东西。

谁可以为我提供一个相当重写的代码,它可以做同样的事情?

#include <functional>
#include <vector>

typedef std::function<bool(int)> Tester_t;
typedef std::vector<Tester_t> TesterSet_t;

bool Test(TesterSet_t &candidates, int foo)
{
    TesterSet_t dropouts;
    for( auto& tester : candidates )
    {
        if(!tester(foo))    
        {
            droputs.push_back(tester);
        }
    }

    while(!dropouts.empty())
    {
        // The following line is not compiling because std::function has no operator==()
        TesterSet_t::iterator culprit = 
            std::find( candidates.begin(), candidates.end(), dropouts.back() );
        candidates.erase(culprit);
        dropouts.pop_back();
    }
    return !candidates.empty();
}

4 个答案:

答案 0 :(得分:10)

正如其他人所说,你不需要对std::function进行比较。使用标准C ++工具,可以有效地(线性复杂性)实现两行:

bool Test(TesterSet_t &candidates, int foo)
{
    candidates.erase(std::remove_if(candidates.begin(), candidates.end(),
        [foo](Tester_t& f){ return !f(foo); }), candidates.end());
    return !candidates.empty();
}

答案 1 :(得分:2)

这里你不需要平等。随便擦除

for (auto it = candidates.begin(); it != candidates.end(); ) {
    if (! (*it)(foo) ) {
        it = candidates.erase(it);
    }
    else {
        ++it;
    }
}
return !candidates.empty();

即使为operator==定义了std::function,这也会比问题中的版本更快。

答案 2 :(得分:0)

如果你不需要删除候选人,你可以写:

bool Test(TesterSet_t &candidates, int foo)
{
    return std::any_of(candidates.begin(), candidates.end(), [&foo](Tester_t &tester) {
        return tester(foo);
    });
}

<强>更新

好的,你需要删除候选人

bool Test(TesterSet_t &candidates, int foo)
{
    candidates.erase(
        std::remove_if(candidates.begin(), candidates.end(), [&foo](Tester_t &tester) {
            return !tester(foo);
        }),
        candidates.end()
    );
    return !candidates.empty();
}

答案 3 :(得分:0)

在这种情况下,简单的答案是而不是使用std::function<...>,而是像std::function<...>那样定义了相等运算符。为function<...>定义等于运算符的方法是在构造时检测实际的函数对象是否实际包含相等运算符,如果是,则使对象具有可比性。否则,您要么产生错误,要么认为持有此特定函数对象类型的对象是无法比拟的。

然而,立即观察到大多数功能对象无法比较!例如,lambda函数不具有可比性,std::bind()std::mem_fn()也不会产生类似的函数对象。同样,std::bind()std::mem_fn()可以有自定义实现。没有办法使lambda函数与相当,除非有一个空捕获,在这种情况下它们可以转换为函数指针并且可以进行比较。

等式感知函数对象的实现有点太长,无法快速键入响应。不过,您可以查看我在github的实施情况,了解可比性bind()mem_fn()。有关std::function<...>的可比较版本的实现,请参阅this answer。如果lambda函数具有相同的签名并且所有捕获的值具有相等的可比性,则可能需要使lambda函数具有可比性。

所有这一切,如果你能避免这种需要,最好避免。但是,我遇到过一些使用情况,尽管有限制(即不是所有的功能对象都会被覆盖),但可比的std::function<...>会相当方便。