title: more spirit madness - parser-types (rules vs int_parser<>) and meta-programming techniques
body: <p>The question is in bold at the bottom, the problem is also summarized by the distillation code fragment towards the end.</p>
  <p>I am trying to unify my type system (the type system does to and from from type to string) into a single component(as defined by Lakos). I am using <code>boost::array</code>, <code>boost::variant</code>, and <code>boost::mpl</code>, in order to achieve this. I want to have the parser and generator rules for my types unified in a variant. there is a undefined type, a int4(see below) type and a int8 type. The variant reads as <code>variant&lt;undefined, int4,int8&gt;</code>.</p>
  <p>int4 traits:</p>
  <pre class="lang-cpp prettyprint-override"><code>    struct rbl_int4_parser_rule_definition
      {
        typedef boost::spirit::qi::rule&lt;std::string::iterator, rbl_int4()&gt; rule_type;
        
        boost::spirit::qi::int_parser&lt;rbl_int4&gt; parser_int32_t;
        
        rule_type rule;
        
        rbl_int4_parser_rule_definition()
        {
          rule.name(&quot;rbl int4 rule&quot;);
          rule = parser_int32_t;  
        }
      };
      
      template&lt;&gt;
      struct rbl_type_parser_rule&lt;rbl_int4&gt;
      {
        typedef rbl_int4_parser_rule_definition string_parser;
      };
  </code></pre>
  <p>the variant above starts out as undefined, and then I initialize the rules. I had a problem, which caused 50 pages of errors, and I have finally managed to track it down, Variant uses <code>operator=</code> during assignment and a <code>boost::spirit::qi::int_parser&lt;&gt;</code> cannot be assigned to another (operator=).</p>
  <p>To contrast, I don't have a problem with my undefined type:</p>
  <pre class="lang-cpp prettyprint-override"><code>    struct rbl_undefined_parser_rule_definition
      {
        typedef boost::spirit::qi::rule&lt;std::string::iterator, void()&gt; rule_type;
        rule_type rule;
        
        rbl_undefined_parser_rule_definition()
        {
          rule.name(&quot;undefined parse rule&quot;);
          rule = boost::spirit::qi::eps;
        }
      };
      
      template&lt;&gt;
      struct rbl_type_parser_rule&lt;rbl_undefined&gt;
      {
        typedef rbl_undefined_parser_rule_definition string_parser;
      };
  </code></pre>
  <p>Distillation of the problem:</p>
  <pre class="lang-cpp prettyprint-override"><code>    #include &lt;string&gt;
      #include &lt;boost/spirit/include/qi.hpp&gt;
      #include &lt;boost/variant.hpp&gt;
      #include &lt;boost/cstdint.hpp&gt;
      
      typedef boost::spirit::qi::rule&lt;std::string::iterator,void()&gt; r1;
      typedef boost::spirit::qi::rule&lt;std::string::iterator,int()&gt; r2;
      
      typedef boost::variant&lt;r1,r2&gt; v;
      
      int main()
      {
        /*
        problematic
        boost::spirit::qi::int_parser&lt;int32_t&gt; t2;
        boost::spirit::qi::int_parser&lt;int32_t&gt; t1;
        
        
        t1 = t2;
        */
      
        //unproblematic
        r1 r1_;
        r2 r2_;
        r1_ = r2_;
      
        v v_;
        // THIS is what I need to do.
        v_ = r2();
      }
  </code></pre>
  <p>There is a semantic gap between concrete parsers and rules. My brain is smoking at the moment so I am not going to think about pramatism, <strong>My question is, how do I solve this problem ?</strong>  I can think of three approaches to solve the problem.</p>
  <p><strong>one:</strong> Static function members:</p>
  <pre class="lang-cpp prettyprint-override"><code>    struct rbl_int4_parser_rule_definition
      {
        typedef boost::spirit::qi::rule&lt;std::string::iterator, rbl_int4()&gt; rule_type;
        
        //boost::spirit::qi::int_parser&lt;rbl_int4&gt; parser_int32_t;
        
        rule_type rule;
        
        rbl_int4_parser_rule_definition()
        {
          static boost::spirit::qi::int_parser&lt;rbl_int4&gt; parser_int32_t;
      
          rule.name(&quot;rbl int4 rule&quot;);
          rule = parser_int32_t;  
        }
      };
  </code></pre>
  <p>I guess approach one prevents thread safe code  ? ?</p>
  <p><strong>two:</strong> The integral parser is wrapped in a shared_ptr. There are two reasons I'm bothering with TMP for the typing system: 1 efficiency, 2 centralizing concerns into components. using pointers defeats the first reason.</p>
  <p><strong>three:</strong> operator= is defined as a no-op. variant guarantees that the <code>lhs</code> is default constructed before assignment.</p>
  <p><strong>Edit:</strong>
  I am thinking option 3 makes the most sense (operator= is a no-op). Once the rule container is created it will not change, and I am only assigning to force a type's rule trait into its offset.</p>