为什么mem_fn()抱怨尝试使用已删除的函数?

时间:2016-10-09 01:41:15

标签: c++ c++11

我有以下代码段:

struct Foo {
    Foo(int num):num_(num){}
    void print_add(int i) const { std::cout << num_+i << '\n'; }
    int num_;
};

int main() {
    std::vector<Foo*> vpf{ new Foo(3), new Foo(4), new Foo(5) };

    auto pfa =  std::mem_fn(&Foo::print_add);
    int i = 42;

    //std::for_each(vpf.begin(), vpf.end(), [&i](const auto& val){val -> print_add(i);});
    std::for_each(vpf.begin(), vpf.end(), pfa(&i));

    return 0;
}

使用lambda表达式的注释代码实际上可以正常工作,因为我希望打印45,46,47。使用std::for_each的{​​{1}}的未注释代码会导致编译错误mem_fn

有人可以解释为什么以及如何在这种情况下正确使用attempt to use a deleted function

3 个答案:

答案 0 :(得分:1)

我看不出你怎么可能从这段代码中获得“尝试使用已删除的函数”错误。代码不准确,或者诊断消息不是列表中的第一个。

此代码中的第一个错误是指您的pfa(&i)子表达式,该表达式无效。首先,为了调用 pfa,您必须提供两个参数 - Foo *int类型 - 而您只提供一个{{} 1}}类型。其次,在int *的情况下,你根本不应该自己调用 std::for_each,你应该传递 pfa本身到pfa

如果你想用“lambdaless”替换你的lambda,例如使用“经典”std::for_each功能对象,它看起来如下

std::mem_fn

或使用现已弃用的C ++ 98库功能

auto pfa = std::mem_fn(&Foo::print_add);
int i = 42;
std::for_each(vpf.begin(), vpf.end(), std::bind(pfa, std::placeholders::_1, i));

(那时候它只是......更加有趣。更多有趣 .Geddit?哈哈哈......)

PS 请注意(如评论中注明的@TC),如果您打算使用{{1},则无需预先将成员指针包装到auto pfa = std::mem_fun(&Foo::print_add); int i = 42; std::for_each(vpf.begin(), vpf.end(), std::bind2nd(pfa, i)); } 在上面。第一个变体可以重写为

std::mem_fn

答案 1 :(得分:0)

std::mem_fn创建一个仿函数,它将引用或指向该类型的指针作为第一个参数,并将其余参数转发给实际函数。

将其传递给算法时,您不应该将其称为()运算符(您没有为lambda示例执行此操作)。你的问题是你也想为你的函数提供一个参数,而这仅仅是mem_fn是不可能的。不过,您可以使用std::bind或lambda执行此操作。

std::for_each(vpf.begin(), vpf.end(), std::bind(pfa, std::placeholders::_1, i));

std::for_each(vpf.begin(), vpf.end(), [&i,&pfa](const auto& val){ pfa(val, i); });

话虽如此,我认为最好从你的例子中使用lambda。 bind是有争议的,如果您还在使用lambda,那么将mem_fn添加到其中的重点是什么?

答案 2 :(得分:0)

auto pfa =  std::mem_fn(&Foo::print_add);

&Foo::print_add不是函数指针。它是一个类方法指针。您不能将其作为函数指针调用。你必须为这个方法提出一个类的实例,并通过指针调用实例的方法。

std::for_each(vpf.begin(), vpf.end(), pfa(&i));

您正在尝试调用pfa,就好像它是一个函数指针一样。首先,对于每次调用,std::for_each都会按照迭代的顺序传递项目。这将成为您需要与方法指针一起使用的类实例:

std::for_each(vpf.begin(), vpf.end(),
          [&i,&pfa](const auto& val){pfa(val, i);});

lambda获取其参数,序列std::for_each中的值迭代,并使用它通过方法指针调用类方法。正如所料,此结果是

45
46
47