'How to define recursive std::variant?

I used to ask a question about recursive std::variant. According to comments, recursive std::variant is an undefined behavior, so I tried some tricks to make recursive std::variant legally. The code shows below:

#include <variant>
#include <vector>
#include <memory>
#include <map>

template<typename T>
struct wrapper {
    wrapper(const T& t) {
        p = std::make_unique<T>(t);
    }

    wrapper(const wrapper& other) {
        p = std::make_unique<T>(*other.p.get());
    }

    wrapper& operator= (const wrapper& other) {
        p = std::make_unique<T>(*other.p.get());
        return *this;
    }
    ~wrapper() = default;

    std::unique_ptr<T> p;
    auto operator<=> (const wrapper& other) const {
        return p <=> other.p;
    }
};

struct var : public std::variant<
    int,
    double,
    wrapper<std::vector<var> >,
    wrapper<std::map<var, var> >
> {};


int main() {
    var v1{ int{1} };
    var v2{ double{2.0} };
    
    wrapper vec(std::vector<var>{v1, v2} ) ;

    var v3(vec);

    std::map<var, var> m{};
    m[v1] = v2;
    wrapper ma{m};
    var v4(ma);
}

In my opinion, std::unique_ptr support incomplete type, so I use it as a wrapper. However, in gcc 11.3 and gcc 10.3, the code works well. But in gcc 11.1 and gcc 11.2, the code can't compile. My questions are:

  1. why gcc 11.1 and gcc 11.2 cannot compile the code?
  2. Is such code legal in c++?
  3. Any better way to write recursive std::variant?


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source