简体   繁体   English

如何存储从 std::bind 返回的可调用对象以获取指向成员函数的指针?

[英]How to store the returned callable from std::bind for a pointer to a member function?

I want to know how to declare an object of the return type of std::function when used with pointer to a member function:我想知道如何在与指向成员函数的指针一起使用时声明std::function返回类型的对象:

int main(){

    void foo(std::string, int);
    string s = "hi";
    auto fn = std::bind(foo, s, std::placeholders::_1);
    fn(5);// ok

    /*auto fn2 = */std::bind(&std::string::empty, std::placeholders::_1); // error if I uncomment /*auto fn2 = */

    std::vector<std::string> vs{"The", "Quick", "Brown", "Fox", "Jumped", "", "Over", "The", "", "Lazy", "Dog"};
    auto it = std::find_if(vs.cbegin(), vs.cend(),
    std::bind(&std::string::empty, std::placeholders::_1)); // OK
    std::cout << "Empty string found at index: " << (it != vs.cend() ? std::distance(vs.cbegin(), it) : -1) << '\n'; // 5

    std::cout << "\ndone!\n";
}
  • If I un-comment auto fn2 = I get an error:如果我取消注释auto fn2 =我得到一个错误:

||=== Build: Debug in myproj (compiler: GNU GCC Compiler) ===| /home/Itachi57/Desktop/myproj/main.cxx||In function 'int main()':| /home/Itachi57/Desktop/myproj/main.cxx|845| in 'constexpr' expansion of 'std::bind(_Func&&, _BoundArgs&& ...) [with _Func = bool (std::__cxx11::basic_string<char>::*)() const noexcept; _BoundArgs = {const std::_Placeholder<1>&}; typename std::_Bind_helper<std::__is_socketlike<_Func>::value, _Func, _BoundArgs ...>::type = std::_Bind_helper<false, bool (std::__cxx11::basic_string<char>::*)() const noexcept, const std::_Placeholder<1>&>::type](std::placeholders::_1)'| /home/Itachi57/Desktop/myproj/main.cxx|845|internal compiler error: Segmentation fault| ||=== Build failed: 2 error(s), 0 warning(s) (0 minute(s), 7 second(s)) ===|

  • So Why if I call bind without storing its returned value using auto when binding a pointer to a member function is OK but I can't store that value (new callable)?那么,为什么在bind指针绑定到成员函数时调用bind而不使用auto存储其返回值是可以的,但我无法存储该值(新的可调用)?

  • In fact this is just for practice purpose because in real I'd prefer to use std::mem_fn and std::function .事实上,这只是为了练习目的,因为实际上我更喜欢使用std::mem_fnstd::function

  • Update:更新:

If I run the program from a terminal:如果我从终端运行程序:

  g++ main.cxx -std=c++2a -o prog && ./prog

It works just fine.它工作得很好。

I've found out that one day I've disabled "Copy-elision optimization" from CodeBlocks:我发现有一天我从 CodeBlocks 中禁用了“复制省略优化”:

 -fno-elide-constructors 

Now If I remove this and let the CodeBlocks apply it (Copy-elision opt.) the program build and works just fine!现在,如果我删除它并让 CodeBlocks 应用它(Copy-elision 选项),程序构建并运行得很好!

  • So does this error have a relationship with Copy-Elision Optimization?那么这个错误与 Copy-Elision Optimization 有关系吗? Thank you!谢谢!

// error if I uncomment /*auto fn2 = */ // 如果我取消注释 /*auto fn2 = */
// OK // 好的

Actually, no, it's not okay.实际上,不,这不好。 The C++ standard doesn't generally permit taking the address of functions defined in namespace std (be they free or members). C++ 标准通常不允许获取命名空间 std 中定义的函数的地址(无论它们是自由的还是成员的)。 The exceptions are always marked explicitly as addressable functions, and std::string::empty is not addressable.异常总是显式标记为可寻址函数,并且std::string::empty不可寻址。

Why?为什么? Implementation leeway and future proofing.实施余地和未来证明。 The standard may want to add overloads.标准可能想要添加重载。 The implementation may want to use overloads to implement the standard-mandated behavior, or even templates.实现可能希望使用重载来实现标准规定的行为,甚至模板。 For that to be possible, and our program be well-defined by the standard, we cannot do &std::string::empty .为了使这成为可能,并且我们的程序被标准明确定义,我们不能做&std::string::empty

Just use lambdas to wrap standard functions that aren't addressable (as you would anyway with your own overload sets).只需使用 lambda 来包装不可寻址的标准函数(就像您使用自己的重载集一样)。 Actually... just use lambdas and forget about std::bind , they are better in practically every way.实际上......只需使用 lambdas 而忘记std::bind ,它们实际上在各个方面都更好。

It's perfectly fine:完全没问题:

Live On Coliru住在 Coliru

#include <functional>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

void foo(std::string, int) {}

int main()
{
    auto fn = std::bind(&std::string::empty, std::placeholders::_1);

    std::vector<std::string> vs{"The",  "Quick", "Brown", "Fox",  "Jumped", "",
                                "Over", "The",   "",      "Lazy", "Dog"};

    auto it = std::find_if(vs.cbegin(), vs.cend(), fn);

    std::cout << "Empty string found at index: "
              << (it != vs.cend() ? std::distance(vs.cbegin(), it) : -1)
              << '\n'; // 5

    std::cout << "\ndone!\n";
}

Prints印刷

Empty string found at index: 5

done!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM