$include_dir="/home/hyper-archives/boost-users/include"; include("$include_dir/msg-header.inc") ?>
From: Anders Dalvander (boost_at_[hidden])
Date: 2007-08-13 12:51:30
Hi,
I'm trying to create a parser that shall create a number of derived 
classes based on the input, put it in a shared_ptr<Base> and push_back 
to a vector.
Example:
"Alpha" => vec.push_back(shared_ptr<Base>(new Alpha()))
"Beta[1]" => vec.push_back(shared_ptr<Base>(new Beta(1)))
"Gamma[2-3]" => vec.push_back(shared_ptr<Base>(new Gamma(2, 3)))
"Gamma[4-End]" => vec.push_back(shared_ptr<Base>(new Gamma(4)))
I've defined the actor as [push_back_a(self.vec, BasePtr(new Alpha()))], 
but that obviously doesn't work as BasePtr(new Alpha()) creates a 
temporary shared_ptr that will be destroyed by the end of the statement. 
How can I delay the creation of the shared_ptr, and how can I delay the 
new statement?
Using Boost 1.34.1, MSVC++ 2005.
Thanks,
Anders Dalvander
#include <vector>
#include <boost/optional.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/spirit.hpp>
#include <boost/spirit/actor/push_back_actor.hpp>
#include <boost/spirit/phoenix.hpp>
using namespace boost::spirit;
using namespace phoenix;
class Base
{
public:
  virtual ~Base() = 0 {}
};
typedef boost::shared_ptr<Base> BasePtr;
class Alpha : public Base
{
public:
  Alpha() {}
  virtual ~Alpha() {}
};
class Beta : public Base
{
public:
  explicit Beta(int var) : var(var) {}
  virtual ~Beta() {}
private:
  int var;
};
class Gamma : public Base
{
public:
  explicit Gamma(int var1) : var1(var1), var2() {}
  Gamma(int var1, int var2) : var1(var1), var2(var2) {}
  virtual ~Gamma() {}
private:
  int var1;
  boost::optional<int> var2;
};
struct my_grammar : grammar<my_grammar>
{
  template <typename ScannerT>
  struct definition
  {
     typedef rule<ScannerT> rule_t;
     explicit definition(const my_grammar& self)
     {
        my_rule
           = str_p("Alpha")[push_back_a(self.vec, BasePtr(new Alpha()))]
           | ("Beta[" >> int_p[var(var1) = arg1] >> 
"]")[push_back_a(self.vec, BasePtr(new Beta(var1)))]
           | ("Gamma[" >> int_p[var(var1) = arg1] >> "-" >> 
int_p[var(var2) = arg1] >> "]")[push_back_a(self.vec, BasePtr(new 
Gamma(var1)))]
           | ("Gamma[" >> int_p[var(var1) = arg1] >> 
"-End]")[push_back_a(self.vec, BasePtr(new Gamma(var1)))]
           ;
     }
     int var1;
     int var2;
     rule_t my_rule;
     const rule_t& start() const
     {
        return my_rule;
     }
  };
  my_grammar(std::vector<BasePtr>& vec)
   : vec(vec)
  {
  }
  std::vector<BasePtr>& vec;
};
int main()
{
  std::vector<BasePtr> vec;
  my_grammar g(vec);
  parse("Alpha", g);
  parse("Beta[1]", g);
  parse("Gamma[2-3]", g);
  parse("Gamma[4-End]", g);
}