类内的 std::function 初始化

Mic*_*ndr 4 c++ c++11 std-function

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

这是我收到的错误消息:

functor.cc:37:9:错误:无法转换‘{{"A", ((C*)this)->C::f}, {"B", ((C*)this)->C::g}, {"C", ((C*)this)->C::h}}’‘<brace-enclosed initializer list>’‘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);
}
Run Code Online (Sandbox Code Playgroud)

eer*_*ika 6

std::function<bool(const std::vector<std::string>&)
Run Code Online (Sandbox Code Playgroud)

该函数对象类型只能包装具有签名的函数bool(const std::vector<std::string>&)。但是,尝试使用的函数都没有这样的签名,因为它们是(非静态)成员函数。此外,您必须使用地址的运营商明确地得到一个指向一个成员函数的名称必须是完全合格的,像这样:&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
};
Run Code Online (Sandbox Code Playgroud)

您也可以使用 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.
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您实际上并不需要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);
Run Code Online (Sandbox Code Playgroud)

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