【问题标题】:std::function initialization inside class类内的 std::function 初始化
【发布时间】:2017-05-30 14:00:05
【问题描述】:

我试图了解 std::function 是如何工作的,但我无法编译它,我不明白为什么。我认为这与在类中使用 std::function 有关,因为没有类(在全局范围内定义的映射)它可以工作。

这是我收到的错误消息:

functor.cc:37:9: 错误:无法将 ‘{{"A", ((C*)this)->C::f}, {"B", ((C*)this)->C::g}, {"C", ((C*)this)->C::h}}’‘&lt;brace-enclosed initializer list&gt;’‘std::map<std::__cxx11::basic_string<char>, std::function<bool(const std::vector<std::__cxx11::basic_string<char> >&)> >’

示例代码(没有意义,但它很好地代表了我遇到的问题):

#include <iostream>
#include <map>
#include <functional>
#include <vector>


class C { 
    public:
        bool f(const std::vector<std::string>& s) {
            std::cout << "F" << std::endl;
            for (auto& i : s) {
                std::cout << i << std::endl;
            }
            return true;
        }

        bool g(const std::vector<std::string>& s) {
            std::cout << "G" << std::endl;
            for (auto& i : s) {
                std::cout << i << std::endl;
            }
            return true;
        }

        bool h(const std::vector<std::string>& s) {
            std::cout << "H" << std::endl;
            for (auto& i : s) {
                std::cout << i << std::endl;
            }
            return true;
        }

        std::map<std::string, std::function<bool(const std::vector<std::string>&)> >  funcMap {
            {"A", f},
            {"B", g},
            {"C", h}
        };
};


int main() {
    std::vector<std::string> v{"mno", "pqr", "stu"};
    C c;
    c.funcMap["A"](v);
}

【问题讨论】:

    标签: c++ c++11 std-function


    【解决方案1】:
    std::function<bool(const std::vector<std::string>&)
    

    该函数对象类型只能包装具有签名bool(const std::vector&lt;std::string&gt;&amp;) 的函数。但是,尝试使用的函数都没有这样的签名,因为它们是(非静态)成员函数。此外,您必须显式使用 address-of 运算符来获取指向成员函数的指针,并且名称必须是完全限定的,如下所示:&amp;C::f

    您可以将this 绑定到成员函数,这将产生一个具有适当签名的函数对象:

    std::map<std::string, std::function<bool(const std::vector<std::string>&)> >  funcMap {
        {"A", std::bind(&C::f, this, std::placeholders::_1)},
        {"B", std::bind(&C::g, this, std::placeholders::_1)},
        {"C", std::bind(&C::h, this, std::placeholders::_1)}
                               ^ we bind this pointer to the function object
    };
    

    您也可以使用 lambda。绑定函数和 lambda 大多只是编写同一事物的两种方式。


    或者,您实际上可能打算只存储成员函数而不是函数对象中的对象指针。在这种情况下,您的函数对象的类型以及您调用它的方式都是错误的。这会起作用:

    std::map<std::string, std::function<bool(C*, const std::vector<std::string>&)> >  funcMap {
    //                                       ^ note the pointer argument for this
        {"A", &C::f},
        {"B", &C::g},
        {"C", &C::h}
    };
    
    // call
    c.funcMap["A"](&c, v);
    //              ^ The object on which the member function is called. 
    //                It doesn't necessarily have to be the same whose funcMap is used.
    

    在这种情况下,您实际上并不需要std::function。成员函数指针的映射就足够了。调用成员函数指针的语法和使用函数对象有点不同:

    std::map<std::string, bool (C::*)(const std::vector<std::string>&) >  funcMap {
        {"A", &C::f},
        {"B", &C::g},
        {"C", &C::h}
    };
    
    // call
    (c.*c.funcMap["A"])(v);
    

    但是,考虑到成员函数都没有使用对象的状态,因此还不清楚为什么需要使用成员函数。另一个简单的解决方案是首先不使用非静态函数。

    【讨论】:

    • 太好了,成功了。我仍在为 std::function、std::bind、原始函数指针、命名 lambda 函数以及何时使用它们而苦苦挣扎。这只是一个简单的例子,我只是想根据 std::map 中的键调用不同的函数。
    • @MichalŠpondr 什么是命名 lambda 函数?
    • 命名 lambda 函数:auto func = [] () { cout
    • @MichalŠpondr 是一个 lambda。为什么叫它“命名”? Lambda 是未命名的函数对象。
    • 因为您可以使用 lambda 函数而无需分配给变量 func。我不明白为什么使用 auto func = [](){};当我可以创建具有相同名称的标准函数时,重复使用 func。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-22
    • 2021-08-11
    • 2020-03-26
    • 2020-10-20
    相关资源
    最近更新 更多