0

I'm currently making a C++ version of python's svg.path. There are multiple types of paths, like a Line, CubicBezier, etc. which are separate classes (with no inheritance, except for Line and Close which are inherited from Linear but that can be removed if necessary). There's also a Path class, which in python has a list of segments. But I'm not sure how to have a vector of segments in C++.

So something like this:

class Line {};
class CubicBezier {};
class Arc {};

class Path {
    // Segment should be able to store any type of Segment like Line, Arc, etc.
    vector<Segment> segments;
};

Currently the best thing I can think of is where I have a Segment class that stores all the segment types and has various setters and getters for each of them, but that seems tedious and annoying, as well as inefficient.

Also, if there's a better way to do this (and there almost certainly is), please explain how to do that, and I'll try it.

If needed, I can post the python code from svg.path.

Ritwin
  • 23
  • 1
  • 6
  • Can a `Path` contain more than one kind of `Segment`? Also, that kinds of things can you do with a `Path`? – Paul Sanders Jun 22 '21 at 01:06
  • If you don't like inheritance, how about `std::any` or `std::variant`? You still have to specify the type when getting though. – Nyque Jun 22 '21 at 01:10
  • @Paul Sanders: Yes. Otherwise I'd have a template like `Path`. – Ritwin Jun 22 '21 at 01:10
  • In that case, I'd use polymorphism. Have a base class, `Segment` from which `Line`, `Arc` etc derive. Define virtual functions for all the things that a `Segment` can do (like draw itself, perhaps). Finally, use a `std::vector >` to store them all in a `Path` (you can't use `std::vector ` as this will cause object slicing). – Paul Sanders Jun 22 '21 at 01:13
  • Paul Sanders: Ok, I'll try that. Does 'object slicing' mean that there's a difference in sizeof(segment) for each segment, so indexing won't work? Nyque: Hmm... just looked at the documentation for it, and I might be able to use that. I'll look into it a bit more to see which way will be easier to implement. – Ritwin Jun 22 '21 at 01:16
  • Pretty much. It's discussed [here](https://stackoverflow.com/questions/274626/what-is-object-slicing). – Paul Sanders Jun 22 '21 at 01:19

1 Answers1

0

Since you're not using inheritance, you'll need a different tool. It appears you want something like std::variant<Line, CubicBezier, Arc>.

The downside of this approach is that you'll need to handle all the different cases yourself, since there's no common base class interface.

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • I wouldn't call it a downside as much as a "where does the type-specific implementation go": in the overriding member functions (which may or may not make sense) or in the visitor function overloads. Both approaches might work, and the variant approach is less flexible to external extension (as the "main" library defines which types are allowed, whereas a base class approach theoretically allows a "user" to provide their own specific subclass without needing to alter the "library" code to accommodate it. – rubenvb Jun 22 '21 at 10:37