c++ - Bison 中的 std::shared_ptr 导致成员错误

标签 c++ bison smart-pointers flex-lexer

我正在尝试通过使用 std::shared_ptr 使 Bison 的内存效率更高。 .我不想使用原始指针。我使用节点系统作为解析树,所以我定义 YYTYPEstd::shared_ptr<Node> .用一些简单的语法运行它后,我得到编译错误:

C2039 'blockNode': is not a member of 'std::shared_ptr'



我觉得这很奇怪,因为在 C++ 中运行的等效代码工作得很好
std::shared_ptr<Node> test = std::make_shared<BlockNode>();
我错过了什么?

需要
%code requires {
    typedef void* yyscan_t;
    #include "node.h"
    #include <memory>
    #define YYSTYPE std::shared_ptr<Node>
}

联盟
%union {
    std::shared_ptr<BlockNode> blockNode;
    std::shared_ptr<TestNode> testNode;
}

%type <blockNode> input
%type <testNode> expr

语法
%start program

%%

program : input { *result = $1; } // <- error here
        ;

input: '\n'      { $$ = std::make_shared<BlockNode>();} // <- error here
     ;

%%


节点.h
class Node /*: public std::enable_shared_from_this<Node>*/ {
public:
    std::string myString;
    Node() {}
    ~Node() { std::cout << "destoryed" << myString << std::endl; }
};

class BlockNode : public  Node {
public:
    BlockNode() {
        myString = "block node";
        std::cout << "created" << myString << std::endl;
    }

};

最佳答案

你应该知道的第一件事是这种设计是行不通的。如果您为 bison 使用默认的 C API,则不能使用不易复制的语义类型,因为如果需要重新分配,bison 将按字节复制其堆栈(而且我相信还有其他问题与覆盖字节有关调用析构函数)。如果你想使用共享指针,你应该弄清楚如何使用 C++ API,我认为它已经达到了某种成熟度(虽然我没有使用太多)。你可能会对结果更满意。
无论如何,您的代码还有一些其他问题。
首先,现代 Bison 应用程序不应该#define YYSTYPE ,甚至不在 %code requires 内堵塞。你应该改用

 %define api.value.type { /* SemanticType */ }
如果你这样做了,bison 会告诉你你不能同时使用 %union声明和固定 api.value.type .如果语义类型是 union ,则它是 union 。它也不能是 shared_pointer .既然您似乎希望它是一个成员都是共享指针的 union ,那么它就是一个 union ,您不想以其他方式定义它。
如果你使用 #define YYSTYPE , 并使用 %union ,然后你会发现 %union永远不会被应用。 %union插入 YYSTYPE 的默认定义(如 union YYSTYPE ),但您对 YYSTYPE 的明确定义覆盖它。但是 Bison 不知道你已经这样做了——直到 C 编译器真正编译生成的代码之后它才变得明显——所以它使用你在 %type 中提供的标签重写语义值引用。声明。换句话说,当你说 %type <blockNode> input , bison 将自动更改对 $n 的任何引用这里指的是 input non-terminal 的一个实例通过添加一个字段引用,就像你写了 $n.blockNode (当然,你不能这样做,因为 Bison 已经添加了字段引用)。但是 #define -覆盖YYSTYPE不是 union ,而是 shared_pointer<Node> , 和 shared_pointer<Node>没有 blockNode成员,如 C++ 编译器错误消息所示。
同样,在 input 的规则中, %type声明导致 Bison 发出代码,该代码将分配给(不存在的)blockNode成员。
通过说明我的第一点——你不能使用 shared_pointer作为 C 代码生成器的语义类型或 union 成员——我通过应用上面的建议“修复”了您的代码(即,删除 #define YYSTYPE,并进行了或多或少的最小更改集以避免其他 Bison 和编译器错误,导致以下 reduced reproducible example :
文件 tom.yy
%code requires {
    #include "tom_node.h"
    #include <memory>
}

%code {
    std::shared_ptr<Node> result;
    void yyerror(const char* msg) {
      std::cerr << msg << '\n';
    }
    int yylex();
}

%union {
    std::shared_ptr<BlockNode> blockNode;
    std::shared_ptr<Node> testNode;
}

%type <blockNode> input

%%

program : input  { *result = *$1; /* ?? I don't know the actual intent */ }

input: '\n'      { $$ = std::make_shared<BlockNode>();}
文件 tom_node.h
#ifndef TOM_NODE_H
#define TOM_NODE_H

#include <iostream>
#include <string>

class Node /*: public std::enable_shared_from_this<Node>*/ {
public:
    std::string myString;
    Node() {}
    ~Node() { std::cout << "destroyed" << myString << std::endl; }
};

class BlockNode : public  Node {
public:
    BlockNode() {
        myString = "block node";
        std::cout << "created" << myString << std::endl;
    }

};
#endif
结果是一连串类似的错误,都涉及 std::shared_pointer 的事实。不是一个平凡的类型。这是前几个:
$ bison -o tom.cc tom.yy
$ gcc -Wall -o tom tom.cc -ly
tom.cc:956:9: error: use of deleted function ‘YYSTYPE::YYSTYPE()’
 YYSTYPE yylval;
         ^~~~~~
tom.cc:104:7: note: ‘YYSTYPE::YYSTYPE()’ is implicitly deleted because the default definition would be ill-formed:
 union YYSTYPE
       ^~~~~~~
tom.yy:15:32: error: union member ‘YYSTYPE::blockNode’ with non-trivial ‘constexpr std::shared_ptr<_Tp>::shared_ptr() [with _Tp = BlockNode]’
     std::shared_ptr<BlockNode> blockNode;
                                ^~~~~~~~~
tom.yy:16:27: error: union member ‘YYSTYPE::testNode’ with non-trivial ‘constexpr std::shared_ptr<_Tp>::shared_ptr() [with _Tp = Node]’
     std::shared_ptr<Node> testNode;
                           ^~~~~~~~
tom.cc: In function ‘int yyparse()’:
tom.cc:985:30: error: use of deleted function ‘YYSTYPE::YYSTYPE()’
     YYSTYPE yyvsa[YYINITDEPTH];
                              ^

关于c++ - Bison 中的 std::shared_ptr 导致成员错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61684355/

相关文章:

objective-c - 将 Bison/Flex/Yacc 集成到 XCode 中

在bison中调用c函数

rust - 遍历中RefCell的循环引用借用

c++ - std::string 到 std::chrono time_point

c++ - 指向采用抽象参数的函数的指针

c++ - 重写一个小的 execve shellcode

c++ - 如何使用智能指针替换 char*?

c++ - 在循环中组合元组

c - $n( Bison 的规则)返回上一个标记读取的值

c++ - 如何将 unique_ptr 与 std::copy 一起使用?