-1

The following doesn't work. Is there some way to get around this?

using Node = std::variant<Foo, Bar, std::vector<Node>>;

The error produced is "error: 'Node' was not declared in this scope"

Chris_F
  • 4,991
  • 5
  • 33
  • 63
  • What happened when you tried the code? This fails for the same reason `using type = std::vector;` also fails. – Jason Oct 19 '22 at 18:12
  • 1
    You can do `class Node:public std::variant>{};` (This is not typedef, but works a lot like that) – Botond Horváth Oct 19 '22 at 18:16
  • @BotondHorváth I appreciate it. This does appear to work. It's been a while since I've used C++ and forgot that public inheritance works this way. – Chris_F Oct 19 '22 at 18:33
  • That works. But please be aware of this: https://stackoverflow.com/questions/2034916/is-it-okay-to-inherit-implementation-from-stl-containers-rather-than-delegate I don't know if this is also valid for std::variant. But that means: When you derive from variant, you must have a comment in your code that explains if and why you think this is legal. – habrewning Oct 19 '22 at 20:30

1 Answers1

1

There is a simple reason why such a data structure often cannot exist. You cannot tell the size of it. For all objects the size must be clear already at compile time. But in your case this is not the show stopper. The variant or vector bring their own memory management that makes such things possible.

But the way how the C++ compiler technically ensures that all sizes are known at compile time is to enforce that all types are properly defined before they are used. Therefore recursive definition like you have in your type are not legal in C++.

But there is an exception (in order to allow explicitly things like your type). For structs it possible to have recursive type definition. The reason is that in OOP programming you often need such things (see the discussion here: Linked lists in C++)

The solution then looks like this:

struct Node{
   std::variant<Foo, Bar, std::vector<Node>> value;
};

It looks also incorrect. But indeed C++ accepts it. Node is an incomplete type. For structs this is accepted.

habrewning
  • 735
  • 3
  • 12
  • For my purposes I think the similar solution Botond recommended in his comment works better since I don't have to change anything else. Unless I am missing a downside to using public inheritance in this instance. – Chris_F Oct 19 '22 at 20:16