Bison中的std::shared_ptr导致成员错误。

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

我想通过使用以下方法使bison的内存效率更高 std::shared_ptr. 我不想使用原始指针。我使用节点系统作为解析树,所以我定义了 YYTYPE 作为 std::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
     ;

%%

Node.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;
    }

};

c++ bison smart-pointers flex-lexer
1个回答
3
投票

首先你应该知道的是,这种设计是行不通的。如果你使用默认的C API来处理bison,你就不能使用一个不可复制的语义类型,因为如果bison需要重新分配它的堆栈,它就会字节式地复制它的堆栈(我相信还有其他一些问题与不调用析构函数而覆盖字节有关)。如果你想使用共享指针,你应该研究如何使用C++ API,我认为C++ API已经达到了某种成熟的程度(虽然我没怎么用过)。你可能会对结果更加满意。

不管怎样,你的代码还有一些其他问题。

首先,现代野牛应用程序不应该 #define YYSTYPE,甚至没有在一个 %code requires 块。您应该使用

 %define api.value.type { /* SemanticType */ }

如果你这样做了,野牛就能告诉你,你不能同时使用一个。%union 宣言和固定 api.value.type. 如果语义类型是一个联合体,它就是一个联合体。它不能也是一个 shared_pointer. 既然你似乎希望它是一个成员都是共享指针的联合体,那么它就是一个联合体,你不想用其他方式定义它。

如果你真的使用 #define YYSTYPE,并使用 %union,那么你会发现 %union 永远不会被应用。%union 插入一个默认的 YYSTYPE (如 union YYSTYPE),但你明确定义的 YYSTYPE 覆盖了这一点。但野牛并不知道您已经这样做了 -- 直到 C 编译器实际编译生成的代码时才会发现 -- 所以它使用您在 %type 声明。换句话说,当你说 %type <blockNode> input,野牛会自动将任何引用到 $n 的实例,其中指的是 input non-terminal 通过添加一个字段引用,就像您写的是 $n.blockNode (当然,你一定不能这么做,因为野牛已经添加了字段引用)。但是 #define-覆盖 YYSTYPE 不是一个联盟,是一个 shared_pointer<Node>shared_pointer<Node> 没有 blockNode 成员,正如C++编译器错误信息所显示的那样。

同样,在 inputజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజ %type 声明导致bison发出代码,将分配给(不存在的)的 blockNode 成员。

为了说明我的第一点 -- -- 你不能使用 shared_pointer 作为C代码生成器的语义类型或联合体成员--我应用上面的建议 "修正 "了您的代码(即删除 #define YYSTYPE并做了一些或多或少的修改,以避免其他的野牛和编译器错误,结果如下所示 小样:

文件 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];
                              ^
© www.soinside.com 2019 - 2024. All rights reserved.