V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
sl0000
V2EX  ›  C

求助大佬, Lambda 表达式可以直接转成 Functor 吗?

  •  
  •   sl0000 · 2019-08-21 22:33:04 +08:00 · 3071 次点击
    这是一个创建于 1919 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我想在 std::map 构造的时候直接使用 Lambda 表达式指定排序方式, 但是编译器报错了

    class Person {
    public:
        std::string name;
        int age;
        Person(const std::string & n , int a) {
            name = n;
            age = a;
        }
        class Compare {
        public:
            bool operator()(const Person & lhs, const Person & rhs) {
                return lhs.age < rhs.age;
            }
        };
    };
    
        auto lambda = [](const Person & lhs, const Person & rhs){
            return lhs.age < rhs.age;
        };
        auto wapper = [lambda]() {
            return lambda;
        };
    
    
        bool a = Person::Compare()(Person("p1", 1), Person("p2", 2));
        bool b = wapper()(Person("p1", 1), Person("p2", 2));
    
        // Success
        std::set<Person, Person::Compare> sp; 
    
        // E: Template argument for template type parameter must be a type
        std::set<Person, wapper> sp; 
    
    
    
    
    12 条回复    2019-08-22 00:42:15 +08:00
    noli
        1
    noli  
       2019-08-21 22:37:00 +08:00   ❤️ 1
    std::bind
    sl0000
        2
    sl0000  
    OP
       2019-08-21 22:51:45 +08:00
    @noli 请问需要怎么实现
    ysc3839
        3
    ysc3839  
       2019-08-21 22:57:31 +08:00 via Android   ❤️ 1
    std::set<Person, decltype(lambda)> sp(lambda);
    noli
        4
    noli  
       2019-08-21 23:03:45 +08:00
    wisan
        5
    wisan  
       2019-08-21 23:05:09 +08:00 via Android   ❤️ 1
    lambda 要用 std::move,不然不能拷贝。。更别说当参数了。。
    noli
        6
    noli  
       2019-08-21 23:06:17 +08:00   ❤️ 1
    @ysc3839 #3

    使用 std::function 代替 decltype<lambda> 是否更通用灵活一些?
    ysc3839
        7
    ysc3839  
       2019-08-21 23:07:59 +08:00 via Android   ❤️ 1
    @noli 我觉得不,因为还要多引入一个头文件。
    geelaw
        8
    geelaw  
       2019-08-21 23:11:27 +08:00 via iPhone   ❤️ 1
    说得够明白了:代替 Person::Compare 的必须是一个类型,你的 wapper 不是一个类型,而是一个对象。

    你可以这样

    template <typename TElement, typename TCompare>
    std::set<TElement, TCompare> make_set(TCompare &&cmp)
    {
    return {};
    }

    auto my_set = make_set<Person>([](Person const &a, Person const &b)
    {
    return a.age < b.age;
    });
    blinue
        9
    blinue  
       2019-08-21 23:25:18 +08:00   ❤️ 1
    Compare 在 set 里被默认构造用于比较,lambda 对象的默认构造函数被删除,decltype(lambda)在 C++20 前行不通,只能定义新的类。在 C++20 里,不捕获的 lamda 对象的类型具有默认构造函数,就可以这样了:set<Person, decltype(lambda)>。
    sl0000
        10
    sl0000  
    OP
       2019-08-21 23:35:12 +08:00
    @geelaw 这个编译不能通过呀, 提示
    ````
    In file included from ~/Desktop/learnC++/LearnC++/main.cpp:11:
    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/set:458:19: error: no matching constructor for initialization of 'std::__1::set<Person, (lambda at ~/Desktop/learnC++/LearnC++/main.cpp:36:32), std::__1::allocator<Person> >::value_compare' (aka '(lambda at /Users/cosmojulis/Desktop/learnC++/LearnC++/main.cpp:36:32)')
    : __tree_(value_compare()) {}
    ^
    ~/Desktop/learnC++/LearnC++/main.cpp:34:12: note: in instantiation of member function 'std::__1::set<Person, (lambda at ~/Desktop/learnC++/LearnC++/main.cpp:36:32), std::__1::allocator<Person> >::set' requested here
    return {};
    ^
    ~/Desktop/learnC++/LearnC++/main.cpp:36:15: note: in instantiation of function template specialization 'make_set<Person, (lambda at ~/Desktop/learnC++/LearnC++/main.cpp:36:32)>' requested here
    auto my_set = make_set<Person>([](const Person & a, const Person & b)
    ^
    ~/Desktop/learnC++/LearnC++/main.cpp:36:32: note: candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided
    auto my_set = make_set<Person>([](const Person & a, const Person & b)
    ^
    ~/Desktop/learnC++/LearnC++/main.cpp:36:32: note: candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 0 were provided
    ````
    sl0000
        11
    sl0000  
    OP
       2019-08-21 23:55:04 +08:00
    感谢各位大佬, 今天学到特别多, 我睡了
    geelaw
        12
    geelaw  
       2019-08-22 00:42:15 +08:00
    @sl0000 #10 Oops 你需要对 TCompare 删除 cv qualifiers 并且使用 std::forward。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5386 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 03:34 · PVG 11:34 · LAX 19:34 · JFK 22:34
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.