【问题标题】:C++ map <std::string,static method pointer>?C++ 映射 <std::string,static 方法指针>?
【发布时间】:2021-10-07 05:47:29
【问题描述】:

所以,首先,我很犹豫要不要问这个问题,因为在 SO 上有(基本上)同样的问题,但答案并没有解决我的问题。

我检查过的问题:C++ map<char, static method pointer>?(标记为与How to create class objects dynamically? 重复,但我没有动态创建对象)

我正在开发 PEG 解析器 (cpp-peglib),并希望将字符串(令牌规则名称)映射到静态函数(解析器函数)。

对于那些不熟悉的人,cpp-peglib 将动作作为 lambdas,以 [](const SemanticValues&amp; vs) {} 的形式。

所以我有一个包含静态方法的结构,这些静态方法是我的解析器操作,看起来像这样:

struct T {
    static auto getParser_A() {
        return [](const SemanticValues& vs) {/* return parsed token*/};
    }
    static auto getParser_B() {
        return [](const SemanticValues& vs) {/* return parsed token*/};
    }
};

我想将动作映射到规则的名称,例如:

std::map&lt;std::string,/* static method reference */&gt; actionMap

这样我就可以添加我的规则,例如:

parser[RULE_NAME] = actionMap[RULE_NAME];

我试过这个:

map&lt;string,function&lt;T*&gt;&gt; mapping;

还有这个:

typedef T* (*action)();
map<string,action> mapping;

但我得到could not convert ‘{{"A", T::getParser_A}, {"B", T::getParser_B}}’ from ‘’ to ‘std::map, std::function &gt;’ 两个版本。

我做错了什么? 以及如何将返回 lambda 的静态方法存储在地图中?

【问题讨论】:

  • T::getParser_A 是要获取返回值还是要使用函数?另外,为什么return [](){ ... }?为什么不直接创建一个实际函数static auto parse_b(const SemanticValues&amp; vs) { ... }? | “无法转换‘{{"A", T::getParser_A}, {"B", T::getParser_B}}" - 请发布minimal reproducible example 以重现错误。你说你想要parser[RULE_NAME] = actionMap[RULE_NAME];。你在哪里使用{{ "A",.... 语法?请张贴代码。 lambda 返回什么类型?
  • 所有 getParser_X 是否有相同的返回类型?为什么返回类型是 T*?
  • @KamilCuk 抱歉,我没有包含整个代码,因为它严重依赖 cpp-peglib。我想得到T::getParser_A 的返回值,这将是传递给cpp-peglib 的lambda 函数。不幸的是,我尝试将静态函数传递给解析器,但它不喜欢它(我的意思是编译器)。我有{{"A",T::getParser_A},...} 是地图的初始化。至于lambda返回值,cpp-peglib指定返回值包裹在any
  • @InQusitive 是的,所有 getParser 变体共享一个返回类型,即 cpp-peglib 要求的 any。正如@KamilCuk 指出的那样,我的示例代码缺乏细节。我被困在存储静态函数和 lambda(函数的返回值)本身(两者都不起作用)之间,所以对于问题 T* 是指向 T 的指针,我的示例中的结构

标签: c++


【解决方案1】:

getParser_A 返回一个 lambda,就像一个指向函数的指针。所以指向getPArser_A 的指针是指向返回函数的函数的指针。您可以将其存储在map 中。我假设下面的函数返回一个int

#include <map>
#include <vector>
#include <functional>
#include <string>

struct SemanticValues {};
struct T {
    static auto getParser_A() {
        return [](const SemanticValues& vs) {
            return 1;
        };
    }
    static auto getParser_B() {
        return [](const SemanticValues& vs) {
            return 2;
        };
    }
};

int main() {
    std::map<std::string, 
         // Function that returns a function that returns an int and takes SemanticValues
         std::function<std::function<int (const SemanticValues& vs)> ()> > m;
    m["A"] = T::getParser_A;
    m["B"] = T::getParser_B;
}

【讨论】:

  • 如何调用 m["A"]? m["A"]()()?
  • SemanticValues something; ["A"]()(something)
  • 这很好,但是有什么办法可以初始化它吗?我可能应该在问题中提供更多细节,但所有这些都只是标题,我真的更喜欢地图是 const 但我已经遇到了其他 const 成员的问题
  • 另外,根据 cpp-peglib 的文档,A semantic action can return a value of arbitrary data type, which will be wrapped by peg::any. If a user returns nothing in a semantic action, the first semantic value in the const SemanticValues&amp; vs argument will be returned. 。 peg::any 基本上是 std::any 的 typedef,因此技术上将返回 any
【解决方案2】:

const SemanticValues&amp; 类型的值到T* 类型的std::function 的语法是

std::function<T*(const SemanticValues&)>`

可以为该类型分配任何参数和结果类型正确的 lambda、仿函数或函数指针。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多