如何增加boost :: variant可以处理的类型数量

时间:2016-01-10 06:05:58

标签: c++ boost variant boost-variant

我正在为verilog语言设计一个解析器,其中一个规则有25个组件,我需要一个大的boost :: variant来保存它:

typedef boost::variant<
 shared_ptr<T_module_item__port_declaration>
 ,  shared_ptr<T_module_item__generate_region>
 ,  shared_ptr<T_module_item__specify_block>
 ,  shared_ptr<T_module_item__parameter_declaration>
 ,  shared_ptr<T_module_item__specparam_declaration>
 ,  shared_ptr<T_module_item__net_declaration>
 ,  shared_ptr<T_module_item__reg_declaration>
 ,  shared_ptr<T_module_item__integer_declaration>
 ,  shared_ptr<T_module_item__real_declaration>
 ,  shared_ptr<T_module_item__time_declaration>
 ,  shared_ptr<T_module_item__realtime_declaration>
 ,  shared_ptr<T_module_item__event_declaration>
 ,  shared_ptr<T_module_item__genvar_declaration>
 ,  shared_ptr<T_module_item__task_declaration>
 ,  shared_ptr<T_module_item__function_declaration>
 ,  shared_ptr<T_module_item__local_parameter_declaration>
 ,  shared_ptr<T_module_item__parameter_override>
 ,  shared_ptr<T_module_item__continuous_assign>
 ,  shared_ptr<T_module_item__gate_instantiation>
 ,  shared_ptr<T_module_item__udp_instantiation>
 ,  shared_ptr<T_module_item__module_instantiation>
 ,  shared_ptr<T_module_item__initial_construct>
 ,  shared_ptr<T_module_item__always_construct>
 ,  shared_ptr<T_module_item__loop_generate_construct>
 ,  shared_ptr<T_module_item__conditional_generate_construct>
 > module_item ; 

但g ++抱怨说boost :: variant只能容纳不超过20种类型。

verilogast.h|1129 col 2| error: wrong number of template arguments (25, should be 20)
||   > module_item ; 
||   ^
/usr/include/boost/variant/variant_fwd.hpp|213 col 53| error: provided for ‘template<class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15, class T16, class T17, class T18, class T19> class boost::variant’
||  template < BOOST_VARIANT_AUX_DECLARE_PARAMS > class variant;

我尝试将BOOST_VARIANT_LIMIT_TYPES重新定义为更大的值:

#define BOOST_VARIANT_LIMIT_TYPES 30
#include<boost/variant.hpp>

但错误仍然存​​在,

2 个答案:

答案 0 :(得分:8)

c ++ 98模式中的clang ++和g ++中的错误(你似乎得到的)很短(而且很遗憾)。 在c ++ 11中,错误更大,并揭示了关键问题:

  

错误:类模板&#39; list&#39;
的模板参数太多   typedef typename mpl :: list&lt; T ...&gt; :: type type;

如果查看Boost.MPL documentation,您可以看到需要添加:

#define BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
#define BOOST_MPL_LIMIT_LIST_SIZE 30

默认情况下,您只能使列表的大小为30,40或50,如果您需要更多,则必须生成自定义标题。

Running on Coliru

答案 1 :(得分:1)

我也偶然发现了同样的问题。很遗憾,我无法使用上述解决方案,因为我依赖已经使用boost-variant #define BOOST_MPL_LIMIT_LIST_SIZE 20的其他库。重新编译boost-variant库也不适合我。

因此,我为我的问题设计了一种解决方法。以下代码说明了此解决方法的概念,包含39种类型。

typedef boost::variant<
    A<20>,A<21>,A<22>,A<23>,A<24>,A<25>,A<26>,A<27>,A<28>,A<29>,A<30>,A<31>,A<32>,A<33>,A<34>,A<35>,A<36>,A<37>,A<38>,A<39>
> NextVar;

typedef boost::variant<
    A<1>,A<2>,A<3>,A<4>,A<5>,A<6>,A<7>,A<8>,A<9>,A<10>,A<11>,A<12>,A<13>,A<14>,A<15>,A<16>,A<17>,A<18>,A<19>,NextVar
> TVar;

struct PrintVisitor : public boost::static_visitor<std::string> {
    result_type operator()(const NextVar& n) {
        return n.apply_visitor(*this);
    }

    template<int T>
    result_type operator()(const A<T>& a)  {
        return std::to_string(a.value);
    }
};

int main(int argc, char **args) {
    TVar x = A<35>(); // Implicit conversion! Great!
    PrintVisitor v;
    std::cout << x.apply_visitor(v) << std::endl;
}

解决方案只是创建boost-variant类型的列表(类似于线性列表)。