I have an array with items of type variant that I want to iterator over using the generic std::array iterator. Now I want to do the management of the array with my own class array2
. However, the variant might also contain an object of type array2
which is instantiated using the variant itself, which means that val is already required as a template parameter.
From a logical standpoint this problem seems solvable: I don't use a data member of type val
in array2
, this means memory layout of val can be fixed upon definition. However, I would have to forward declare the val-type to use it in the definition of val. Can I do that somehow? Or is there a more idiomatic approach to this problem / a workaround?
I have checked out C++ Forward declare using directive but it doesn't answer my question because it doesn't use recursion (which makes it a lot easier).
#include <variant>
#include <cstddef>
#include <array>
template <typename T, size_t V> struct array2;
template <size_t V>
using val = std::variant<std::monostate, int, array2<val, V>>;
template <typename T, size_t V>
struct array2
{
using iterator = typename std::array<T, V>::iterator;
iterator begin_; // array allocation not done in here
iterator end_;
};
int main() {}
Yields:
<source>:9:54: error: 'val' was not declared in this scope
9 | using val = std::variant<std::monostate, int, array2<val, V>>;
Update:
Note that array2
's size does not depend on the definition of val, except that the using
declaration does require it for std::array<val, V>
to be complete apparently.