我被困在一个问题上,我知道这里已经发布了一些类似的问题,但我还不能根据他们的回答解决问题。有人可以帮我吗?
我在 .h 文件中有以下类:
class A
{
private:
struct ARGS
{
size_t length{0};
std::string str{""};
};
typedef int(A::*FUNCPTR)(const std::vector<ARGS> &);
std::map<const std::string, FUNCPTR> func_map
{
{"PRINT_HW",
[this](const std::vector<ARGS> args){
validate(args, 0);
A::cmd_phw();
}
},
{"PRINT_NAME",
[this](const std::vector<ARGS> args){
validate(args, 1);
A::cmd_pn(args[0]);
}
},
{"PRINT_NAME_SURNAME",
[this](const std::vector<ARGS> args){
validate(args, 2);
A::cmd_pns(args[0], args[1]);
}
},
};
// function declaration for the existing commands.
int cmd_phw();
int cmd_pn(ARGS args1);
int cmd_pns(ARGS args1, ARGS args2);
static void validate(const std::vector<ARGS> &args, size_t needed)
{
if (args.size() != needed)
{
throw std::invalid_argument("Wrong number of arguments!");
}
}
public:
A(); // Class constructor declaration
int call_print(const std::string& str, const std::vector<ARGS> &args);
};
在 .cpp 文件中我有所有的定义,包括
call_print
如下:
int A::call_print(const std::string& str, const std::vector<ARGS> &args)
{
FUNCPTR fp = func_map[str];
int r = (this->*fp)(args);
return r;
}
但不幸的是它导致了一个错误:
could not convert ‘{{"PRINT_HW", <lambda closure object>A::<lambda(std::vector<A::ARGS>)>{((A*)this)}}, {"PRINT_NAME", <lambda closure object>A::<lambda(std::vector<A::ARGS>)>{((A*)this)}}, {"PRINT_NAME_SURNAME", <lambda closure object>A::<lambda(std::vector<A::ARGS>)>{((A*)this)}}}’ from ‘<brace-enclosed initializer list>’ to ‘std::map<const std::__cxx11::basic_string<char>, int (A::*)(const std::vector<A::ARGS>&)>’
您不能将 lambda 转换为指向成员函数的指针。 lambda 可以转换为普通的指向函数的指针,但前提是它是非捕获。
因为你想使用 capturing lambda,你必须使用
std::function
作为你的 std::map
值类型,例如:
class A
{
public:
struct ARG
{
size_t length{0};
std::string str{""};
};
using ARGS = std::vector<ARG>;
private:
using FUNCPTR = std::function<int(const ARGS&)>;
std::map<std::string, FUNCPTR> func_map
{
{"PRINT_HW",
[this](const ARGS& args) -> int {
A::validate(args, 0);
return cmd_phw();
}
},
{"PRINT_NAME",
[this](const ARGS& args) -> int {
A::validate(args, 1);
return cmd_pn(args[0]);
}
},
{"PRINT_NAME_SURNAME",
[this](const ARGS& args) -> int {
A::validate(args, 2);
return cmd_pns(args[0], args[1]);
}
},
};
// function declaration for the existing commands.
int cmd_phw();
int cmd_pn(const ARG& args1);
int cmd_pns(const ARG& args1, const ARG& args2);
static void validate(const ARGS &args, size_t needed)
{
if (args.size() != needed)
{
throw std::invalid_argument("Wrong number of arguments!");
}
}
public:
A(); // Class constructor declaration
int call_print(const std::string& str, const ARGS &args);
};
int A::call_print(const std::string& str, const ARGS &args)
{
return func_map.at(str)(args);
}
错误消息表明传递给
std::map
构造函数的初始化列表的类型与地图的value_type
的类型不兼容。具体来说,映射的value_type
是int (A::*)(const std::vector<ARGS>&)
,它是指向成员函数类型的指针,而初始化列表提供了具有不同类型的lambda函数。
要修复错误,您需要确保 lambda 函数与指向成员函数的指针具有相同的类型。一种方法是使用与成员函数相同的签名来定义 lambda 函数,如下所示:
{
{"PRINT_HW", &A::cmd_phw},
{"PRINT_NAME", &A::cmd_pn},
{"PRINT_NAME_SURNAME", &A::cmd_pns}
}
或者,您可以为具有正确签名的 lambda 函数定义类型别名,并在映射声明中使用它,如下所示:
using FUNCPTR = int(A::*)(const std::vector<ARGS>&);
using LambdaType = std::function<int(A*, const std::vector<ARGS>&)>;
std::map<std::string, FUNCPTR> func_map {
{"PRINT_HW", static_cast<FUNCPTR>(&A::cmd_phw)},
{"PRINT_NAME", static_cast<FUNCPTR>(&A::cmd_pn)},
{"PRINT_NAME_SURNAME", static_cast<FUNCPTR>(&A::cmd_pns)}
};
为具有正确签名的 lambda 函数定义类型别名
LambdaType
,然后使用 static_cast
将 lambda 转换为指向成员函数的指针类型 FUNCPTR
。请注意,我们还需要传递一个指向对象的指针 (this
) 作为成员函数的第一个参数,当通过指针调用成员函数时。