继承自 boost::variant 和模板化 AST
Inheriting from boost::variant and templatized AST
以下代码 crashes GCC 无法使用 Clang 进行编译。怎么了?
#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";
}
您在构造函数中获得无限递归。
第一个变体成员本身包含 1 个节点的集合。因此,默认构造的 ast_node
s 将递归初始化 wrapper1
,当堆栈溢出时触底。
最简单的修复:
#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";
}
以下代码 crashes GCC 无法使用 Clang 进行编译。怎么了?
#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";
}
您在构造函数中获得无限递归。
第一个变体成员本身包含 1 个节点的集合。因此,默认构造的 ast_node
s 将递归初始化 wrapper1
,当堆栈溢出时触底。
最简单的修复:
#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";
}