我正在尝试通过使用来提高野牛的记忆效率std::shared_ptr
。我不想使用原始指针。我正在使用节点系统作为分析树,因此我定义YYTYPE
为std::shared_ptr<Node>
。使用一些简单的语法运行它之后,我得到了编译错误:
C2039'blockNode':不是'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
;
%%
节点
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,我认为它已经达到某种成熟程度(尽管我没有使用太多)。您可能会更满意结果。
无论如何,您的代码还有其他一些问题。
首先,现代野牛应用程序不应该#define YYSTYPE
甚至不在%code requires
块内。您应该改用
%define api.value.type { /* SemanticType */ }
如果您这样做了,那么bison就能告诉您不能同时使用%union
声明和fixed api.value.type
。如果语义类型是联合,则为联合。它也不能是一个shared_pointer
。由于您似乎希望它是一个其成员都是共享指针的联合,因此它是一个联合,并且您不想以其他方式定义它。
如果您确实使用了#define YYSTYPE
,并且还使用了%union
,那么您将发现%union
永不应用。%union
插入YYSTYPE
(as union YYSTYPE
)的默认定义,但是您的显式定义YYSTYPE
会覆盖该定义。但是bison不知道您已经这样做了-在C编译器实际编译生成的代码之前它不会变得明显-因此它使用%type
声明中提供的标签重写语义值引用。换句话说,当您说时%type <blockNode> input
,bison会通过添加字段引用来自动将任何引用更改为引用$n
实例的位置input non-terminal
,就像您已经写过一样$n.blockNode
(当然,您不可以这样做,因为bison已经添加了字段参考)。但是-被#define
覆盖YYSTYPE
不是联合,而是一个shared_pointer<Node>
,并且shared_pointer<Node>
没有blockNode
成员,如C ++编译器错误消息所示。
同样,在的规则中input
,%type
声明使bison发出将分配给(不存在)blockNode
成员的代码。
通过说明我的第一点(即您不能shared_pointer
与C代码生成器一起用作语义类型或联合成员),我通过应用以上建议“固定”了您的代码(即,删除#define YYSTYPE
,并添加更多或较少的最小更改集,以避免其他bison和编译器错误,从而导致以下减少的可重现示例:
%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>();}
#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];
^
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句