3

The following code crashes GCC and fails to compile with Clang. What's wrong with it?

#include <boost/variant.hpp>
#include <array>
#include <iostream>


template<class Node>
struct wrapper1;
template<class Node>
struct wrapper2;

struct ast_node;
using ast_node_base = boost::variant<boost::recursive_wrapper<wrapper1<ast_node>>, boost::recursive_wrapper<wrapper2<ast_node>>>;

struct ast_node : ast_node_base
{
    using ast_node_base::ast_node_base;
};

template<class Node>
struct wrapper1
{
    std::array<Node, 1> children;
};

template<class Node>
struct wrapper2
{
    std::array<Node, 2> children;
};


int main()
{
    ast_node node;
    std::cout << "done\n";
}
Igor R.
  • 14,716
  • 2
  • 49
  • 83

1 Answers1

2

You get infinite recursion in the constructor.

The first variant member contains itself an aggregate of 1 Node. Default constructed ast_nodes will therefore recursively initialize wrapper1 which bottoms out when the stack overflows.

Simplest fix:

Live On Coliru

#include <array>
#include <boost/variant.hpp>
#include <iostream>

template <class Node> struct wrapper1;
template <class Node> struct wrapper2;

struct nil {};
struct ast_node;
using ast_node_base = boost::variant<nil, boost::recursive_wrapper<wrapper1<ast_node> >, boost::recursive_wrapper<wrapper2<ast_node> > >;

struct ast_node : ast_node_base {
    using ast_node_base::ast_node_base;
};

template <class Node> struct wrapper1 { std::array<Node, 1> children; };
template <class Node> struct wrapper2 { std::array<Node, 2> children; };

int main() {
    ast_node node;
    std::cout << "done\n";
}
sehe
  • 374,641
  • 47
  • 450
  • 633