在没有 unique_ptr 的情况下转换为派生 class
Cast to derived class without unique_ptr
背景
我正在使用 Bison 和 Flex 创建 Cpp 解析器,我偶然发现了一个问题:在我的解析器中,我需要一个基本 class 对象的向量,比方说 shapes.根据对象的派生 class,我需要访问不同的成员。因此,我打算将 unique_ptr 存储在向量中。然后在访问时,我可以动态地将它们转换为它们的派生类型。
问题
但是,我无法让 Bison 正确处理 unique_ptr。无论我如何指定 parser.yy 文件,在编译时我 运行 都会出现类似
的错误
usr/include/c++/9/bits/stl_uninitialized.h:127:72: error: static assertion failed: result type must be constructible from value type of input range
根据 this post Bison 不能很好地处理 unique_ptrs(据我所知,Bison 在内部不使用 std::move() ),我认为情况仍然如此。
我的问题
因为我想保持 class 层次结构不变并且不想修复 Bison 本身的错误:是否有使用 unique_ptrs 的替代方法从 Base class 转换为 Derived class?
代码示例
特别是,我希望在不使用 unique_ptrs 的情况下像下面这样工作。
enum Shape_type{
SHAPE_TYPE_CIRCLE,
SHAPE_TYPE_TRIANGLE,
};
class Shape{
public:
enum Shape_type type;
Shape(enum Shape_type type){ this->type=type; }
virtual ~Shape(){}
};
class Circle: public Shape{
int r;
public:
int get_r(){ return this->r; }
Circle(int r):Shape(SHAPE_TYPE_CIRCLE){ this->r=r; }
};
int main(void){
std::vector<std::unique_ptr<Shape>> shapes;
std::unique_ptr<Shape> circle_ptr = std::make_unique<Circle>(42);
shapes.push_back(std::move(circle_ptr));
for(auto& s_ptr: shapes){
switch(s_ptr->type){
case SHAPE_TYPE_CIRCLE:
{
auto c = dynamic_cast<Circle&>(*s_ptr);
std::cout << "circle with r=" << c.get_r() << std::endl;
break;
}
default: {
std::cout << "other shape" << std::endl;
break;
}
}
}
return 0;
}
非常感谢任何帮助。提前致谢。
多态方式是(用std::shared_ptr
替换不可复制的std::unique_ptr
):
class Shape{
public:
virtual ~Shape() = default;
virtual void draw() const = 0;
};
class Circle: public Shape
{
int r;
public:
explicit Circle(int r): r(r) {}
int get_r() const { return r; }
void draw() const override { std::cout << "circle with r=" << r << std::endl; }
};
class Square: public Shape
{
int side;
public:
explicit Square(int side): side(side) {}
int get_side() const { return side; }
void draw() const override { std::cout << "square with side=" << side << std::endl; }
};
int main()
{
std::vector<std::shared_ptr<Shape>> shapes { std::make_shared<Circle>(42) };
for (const auto& shape_ptr: shapes)
{
shape_ptr->draw();
}
return 0;
}
有了std::variant
,你可能会
class Circle
{
int r;
public:
explicit Circle(int r): r(r) {}
int get_r() const { return r; }
void draw() const { std::cout << "circle with r=" << r << std::endl; }
};
class Square
{
int side;
public:
explicit Square(int side): side(side) {}
int get_side() const { return side; }
void draw() const { std::cout << "square with side=" << side << std::endl; }
};
using Shape = std::variant<Circle, Square>;
int main()
{
std::vector<Shape> shapes { Circle(42) };
for (const auto& shape: shapes)
{
std::visit([](const auto& shape){ shape.draw(); }, shape);
}
return 0;
}
背景
我正在使用 Bison 和 Flex 创建 Cpp 解析器,我偶然发现了一个问题:在我的解析器中,我需要一个基本 class 对象的向量,比方说 shapes.根据对象的派生 class,我需要访问不同的成员。因此,我打算将 unique_ptr 存储在向量中。然后在访问时,我可以动态地将它们转换为它们的派生类型。
问题
但是,我无法让 Bison 正确处理 unique_ptr。无论我如何指定 parser.yy 文件,在编译时我 运行 都会出现类似
的错误usr/include/c++/9/bits/stl_uninitialized.h:127:72: error: static assertion failed: result type must be constructible from value type of input range
根据 this post Bison 不能很好地处理 unique_ptrs(据我所知,Bison 在内部不使用 std::move() ),我认为情况仍然如此。
我的问题
因为我想保持 class 层次结构不变并且不想修复 Bison 本身的错误:是否有使用 unique_ptrs 的替代方法从 Base class 转换为 Derived class?
代码示例
特别是,我希望在不使用 unique_ptrs 的情况下像下面这样工作。
enum Shape_type{
SHAPE_TYPE_CIRCLE,
SHAPE_TYPE_TRIANGLE,
};
class Shape{
public:
enum Shape_type type;
Shape(enum Shape_type type){ this->type=type; }
virtual ~Shape(){}
};
class Circle: public Shape{
int r;
public:
int get_r(){ return this->r; }
Circle(int r):Shape(SHAPE_TYPE_CIRCLE){ this->r=r; }
};
int main(void){
std::vector<std::unique_ptr<Shape>> shapes;
std::unique_ptr<Shape> circle_ptr = std::make_unique<Circle>(42);
shapes.push_back(std::move(circle_ptr));
for(auto& s_ptr: shapes){
switch(s_ptr->type){
case SHAPE_TYPE_CIRCLE:
{
auto c = dynamic_cast<Circle&>(*s_ptr);
std::cout << "circle with r=" << c.get_r() << std::endl;
break;
}
default: {
std::cout << "other shape" << std::endl;
break;
}
}
}
return 0;
}
非常感谢任何帮助。提前致谢。
多态方式是(用std::shared_ptr
替换不可复制的std::unique_ptr
):
class Shape{
public:
virtual ~Shape() = default;
virtual void draw() const = 0;
};
class Circle: public Shape
{
int r;
public:
explicit Circle(int r): r(r) {}
int get_r() const { return r; }
void draw() const override { std::cout << "circle with r=" << r << std::endl; }
};
class Square: public Shape
{
int side;
public:
explicit Square(int side): side(side) {}
int get_side() const { return side; }
void draw() const override { std::cout << "square with side=" << side << std::endl; }
};
int main()
{
std::vector<std::shared_ptr<Shape>> shapes { std::make_shared<Circle>(42) };
for (const auto& shape_ptr: shapes)
{
shape_ptr->draw();
}
return 0;
}
有了std::variant
,你可能会
class Circle
{
int r;
public:
explicit Circle(int r): r(r) {}
int get_r() const { return r; }
void draw() const { std::cout << "circle with r=" << r << std::endl; }
};
class Square
{
int side;
public:
explicit Square(int side): side(side) {}
int get_side() const { return side; }
void draw() const { std::cout << "square with side=" << side << std::endl; }
};
using Shape = std::variant<Circle, Square>;
int main()
{
std::vector<Shape> shapes { Circle(42) };
for (const auto& shape: shapes)
{
std::visit([](const auto& shape){ shape.draw(); }, shape);
}
return 0;
}