Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何解决std::function没有运算符==?_C++_C++11 - Fatal编程技术网

C++ 如何解决std::function没有运算符==?

C++ 如何解决std::function没有运算符==?,c++,c++11,C++,C++11,问题:如果不是因为没有编译,下面的代码将非常有表现力和简洁,如果不一定很快的话 它不会编译,因为无法将std::函数实例与运算符==()进行比较。而std::find()正是试图做到这一点 当然,我可以选择一种完全不同的实现方式,但尽管我很固执,也很喜欢下面的代码,但我正在寻找一种“尽可能接近”的方法 谁能给我一个很好的重写下面的代码做同样的事情 #include <functional> #include <vector> typedef std::function&

问题:如果不是因为没有编译,下面的代码将非常有表现力和简洁,如果不一定很快的话

它不会编译,因为无法将std::函数实例与运算符==()进行比较。而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();
}
#包括
#包括
typedef std::功能测试仪;
typedef std::向量测试仪集;
布尔测试(测试集和候选人,int foo)
{
测试集辍学;
用于(自动测试仪和测试仪:候选)
{
如果(!测试仪(foo))
{
跌落。推回(测试仪);
}
}
而(!dropouts.empty())
{
//由于std::function没有运算符==(),因此未编译以下行
TesterSet_t::迭代器罪魁祸首=
std::find(candidates.begin()、candidates.end()、dropouts.back());
删除(罪犯);
辍学。返回();
}
return!candidates.empty();
}

这里不需要平等。边走边擦

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

即使为
std::function
定义了
operator==
,这也将比问题中的版本快,如果您不需要删除候选项,您可以编写:

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();
}

正如其他人所说,您不需要为此比较
std::function
s。使用标准的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();
}
简单的答案不是在本例中使用
std::function
,而是类似于
std::function
的东西,它定义了一个相等运算符。为
函数定义相等运算符的方法是在构造时检测实际函数对象是否实际包含相等运算符,如果是,则使对象具有可比性。否则,您要么产生错误,要么考虑持有这个特定函数对象类型的对象是不可比拟的。
然而,最直接的观察结果是,大多数功能对象是不可比较的!例如,lambda函数是不可比较的,
std::bind()
std::mem\u fn()
也不会产生可比较的函数对象。同样,可以为
std::bind()
std::mem\u fn()
提供自定义实现。除非具有空捕获,否则无法使lambda函数具有可比性。在这种情况下,可以将lambda函数转换为函数指针并进行比较

平等感知函数对象的实现有点太长,无法快速键入响应。但是,您可以查看我在中的实现,以获得可比的
bind()
mem\u fn()
。有关
std::function
的等效可比版本的实现,请参阅。如果lambda函数具有相同的特征码且所有捕获的值都具有相等的可比性,则可能希望lambda函数也具有可比性


综上所述,如果你能避免这种需要,那么最好是避免。然而,我遇到了一些使用案例,其中一个可比较的
std::function
尽管有限制(即,并非所有的函数对象都将被涵盖),但仍然非常方便。

您能描述一下您试图解决的潜在问题吗?
std::function
没有
=
运算符的原因是,这样比较函数没有任何意义。如何确定两个函数是否相等?类似(可能重复):简短回答:您应该创建一个包含唯一键和
std::function
的结构,并具有这些结构的向量。实际上使用
std::function
作为搜索键没有多大意义。我编写了这个代码片段,这样我就不必用我想在其中使用这种方法的较长代码来打扰任何人。基本上,你有一套选择——我在这里称之为候选人——你用一些输入来面对它,你只想保留那些仍然“在游戏中”的候选人。正如您所说,std::function毫无意义;)@MattMcNabb如果没有人有更好的主意,我会这样做。擦除是其中的一部分。还有,(剩下的)候选人需要试一试。当发现第一个返回false时,代码返回。代码的目标实际上是精简剩余的候选集。迭代时擦除是一条很好的灾难之路。至少多年来一直如此。但也许C++11伏都教现在让它合法了?只要你做得正确,在迭代时擦除总是可以的。@user2225104如果你做得不对,很多事情都会导致灾难。只要学习正确的方法就行了。一般来说,我认为在迭代时更改容器是不可取的。在迭代时擦除是可以的,这是
erase
返回迭代器的主要原因之一!(关联容器在C++03中没有,但在C++11中得到了)。这就是为什么我长期以来认为auto/lambda/std::function方法存在根本性缺陷的原因。他们真的应该引入一种新的内在类型,使函数值和函数引用成为第一流公民。如何解决捕获上下文实现并不是C++用户的问题。有了它,像C这样的努力可能会全部节省下来。问题不在于如何处理捕获。问题在于,您可以捕获不可比较的对象(或对对象的引用)。例如,当不需要比较它们时,您需要为它们使用lambda函数。所以你会