无法从 <brace-enclosed initializer list> 转换为 std::map

问题描述 投票:0回答:2

我被困在一个问题上,我知道这里已经发布了一些类似的问题,但我还不能根据他们的回答解决问题。有人可以帮我吗?

我在 .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>&)>’
c++ arrays pointers function-pointers stdmap
2个回答
1
投票

您不能将 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);
}

-2
投票

错误消息表明传递给

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
) 作为成员函数的第一个参数,当通过指针调用成员函数时。

© www.soinside.com 2019 - 2024. All rights reserved.