我目前正在将一些代码从 ANTLR4 的 C# 版本移植到 C++ 目标,并且我目前遇到了一些问题。我在 C# 中构建我的 AST 的方法是创建一个基类(我们称之为 Base)和派生类(我们称之为派生),其中包含我可以用来实现所述类的虚函数。
但是尝试将此代码转换为 C++,我不断收到 bad_cast 异常
我已将其缩小为 antlrcpp::Any 未正确将派生类转换为其基类。例如:
class Base {
public:
virtual std::string ToString() const { return "Base\n"; }
};
class Derived : public Base {
public:
std::string ToString() const override { return "Derived\n"; }
};
int main() {
Derived value;
std::cout << value.ToString(); //Obviously prints out Derived
Base& base_value = value;
std::cout << base_value.ToString(); //Still works exactly as expected and prints Derived
auto any = antlrcpp::Any(value);
auto derived = any.as<Base>(); //internally uses a dynamic_cast and throws a bad_cast
std::cout << derived.ToString(); //never gets to here
}
我最初认为这可能是因为它只适用于指针,但是
auto any = antlrcpp::Any(new Derived());
std::cout << any.as<Base*>()->ToString(); //throws bad_cast
我将
dynamic_cast
更改为标题内的 static_cast
并且它会进行转换,但是它会打印出“Base”。当任何数据成员被访问时,C 风格的强制转换会导致崩溃。我究竟如何使用
antlrcpp::Any
来获取基类?有什么明显的我遗漏了吗?如果这是不可能的,我该如何解决这个问题?有 .is() 方法,但是在很多情况下,检查访问者的返回值是否属于某种类型是不可行的(例如对于表达式,可以有 30-40 个运算符)。
最佳答案
antlrcpp::any
类不是为那种场景设计的。它不是通用的 Variant 实现。
如果您需要,您应该考虑使用各种类型的 union 等自己的 Variant 实现,这不适用于类型擦除。
通常,在这种情况下,唯一指针可能不是一个好主意,因为它们不支持复制语义(您在这里需要它)。对于访问者的评估,最好使用 shared_ptr
代替。