Hi,

I get a compiler error (cannot convert from 'const phoenix::nil_t' to 'int') when using arg2 of a two value closure. arg1 works fine, but not arg2. I don't understand what I have done wrong.

Visual Studio 2005 SP1
boost 1.36.0

Anyone got any ideas?

Best regards,
Anders Dalvander

Output:

Compiling...
SpiritClosureTest.cpp
d:\prog\boost_1_36_0\boost\spirit\home\classic\phoenix\operators.hpp(446) : error C2440: '=' : cannot convert from 'const phoenix::nil_t' to 'int'
       No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
       d:\prog\boost_1_36_0\boost\spirit\home\classic\phoenix\operators.hpp(446) : while compiling class template member function 'int &phoenix::binary_operator<TagT,T0,T1>::eval(T0 &,const T1 &)'
       with
       [
           TagT=phoenix::assign_op,
           T0=int,
           T1=phoenix::nil_t
       ]
       d:\prog\boost_1_36_0\boost\spirit\home\classic\phoenix\operators.hpp(1017) : see reference to class template instantiation 'phoenix::binary_operator<TagT,T0,T1>' being compiled
       with
       [
           TagT=phoenix::assign_op,
           T0=int,
           T1=phoenix::nil_t
       ]
       d:\prog\boost_1_36_0\boost\spirit\home\classic\phoenix\composite.hpp(237) : see reference to class template instantiation 'phoenix::assign_op::result<T0,T1>' being compiled
       with
       [
           T0=int,
           T1=phoenix::nil_t
       ]
       d:\prog\boost_1_36_0\boost\spirit\home\classic\phoenix\composite.hpp(267) : see reference to class template instantiation 'phoenix::composite2_result<OperationT,TupleT,A,B>' being compiled
       with
       [
           OperationT=phoenix::assign_op,
           TupleT=phoenix::tuple<>,
           A=phoenix::actor<phoenix::closure_member<0,phoenix::closure<int,int,phoenix::nil_t>>>,
           B=phoenix::actor<phoenix::argument<0>>
       ]
       d:\prog\boost_1_36_0\boost\spirit\home\classic\phoenix\actor.hpp(122) : see reference to class template instantiation 'phoenix::composite<OperationT,A,B,C>::result<TupleT>' being compiled
       with
       [
           OperationT=phoenix::assign_op,
           A=phoenix::actor<phoenix::closure_member<0,phoenix::closure<int,int,phoenix::nil_t>>>,
           B=phoenix::actor<phoenix::argument<0>>,
           C=phoenix::as_actor<phoenix::nil_t>::type,
           TupleT=phoenix::tuple<>
       ]
       d:\prog\boost_1_36_0\boost\spirit\home\classic\phoenix\actor.hpp(133) : see reference to class template instantiation 'phoenix::actor_result<ActorT,TupleT>' being compiled
       with
       [
           ActorT=phoenix::composite<phoenix::assign_op,phoenix::actor<phoenix::closure_member<0,phoenix::closure<int,int,phoenix::nil_t>>>,phoenix::actor<phoenix::argument<0>>,phoenix::as_actor<phoenix::nil_t>::type>,
           TupleT=phoenix::tuple<>
       ]
       c:\documents and settings\anders\my documents\visual studio 2005\projects\spiritclosuretest\spiritclosuretest\spiritclosuretest.cpp(25) : see reference to class template instantiation 'phoenix::actor<BaseT>' being compiled
       with
       [
           BaseT=phoenix::composite<phoenix::assign_op,phoenix::actor<phoenix::closure_member<0,phoenix::closure<int,int,phoenix::nil_t>>>,phoenix::actor<phoenix::argument<0>>,phoenix::as_actor<phoenix::nil_t>::type>
       ]
       c:\documents and settings\anders\my documents\visual studio 2005\projects\spiritclosuretest\spiritclosuretest\spiritclosuretest.cpp(16) : while compiling class template member function 'my_grammar::definition<ScannerT>::definition(const my_grammar &)'
       with
       [
           ScannerT=boost::spirit::scanner<>
       ]
       d:\prog\boost_1_36_0\boost\spirit\home\classic\core\non_terminal\impl\grammar.ipp(279) : see reference to class template instantiation 'my_grammar::definition<ScannerT>' being compiled
       with
       [
           ScannerT=boost::spirit::scanner<>
       ]
       d:\prog\boost_1_36_0\boost\spirit\home\classic\core\non_terminal\impl\grammar.ipp(298) : see reference to function template instantiation 'void boost::spirit::impl::call_helper<0>::do_<result_t,definition_t,ScannerT>(RT &,DefinitionT &,const ScannerT &)' being compiled
       with
       [
           ScannerT=boost::spirit::scanner<>,
           RT=result_t,
           DefinitionT=definition_t
       ]
       d:\prog\boost_1_36_0\boost\spirit\home\classic\core\non_terminal\grammar.hpp(55) : see reference to function template instantiation 'boost::spirit::match<boost::spirit::nil_t> boost::spirit::impl::grammar_parser_parse<0,my_grammar,boost::spirit::parser_context<>,ScannerT>(const boost::spirit::grammar<DerivedT> *,const ScannerT &)' being compiled
       with
       [
           ScannerT=boost::spirit::scanner<>,
           DerivedT=my_grammar
       ]
       d:\prog\boost_1_36_0\boost\spirit\home\classic\core\non_terminal\grammar.hpp(65) : see reference to function template instantiation 'boost::spirit::match<boost::spirit::nil_t> boost::spirit::grammar<DerivedT>::parse_main<ScannerT>(const ScannerT &) const' being compiled
       with
       [
           DerivedT=my_grammar,
           ScannerT=boost::spirit::scanner<>
       ]
       d:\prog\boost_1_36_0\boost\spirit\home\classic\core\impl\parser.ipp(30) : see reference to function template instantiation 'boost::spirit::match<boost::spirit::nil_t> boost::spirit::grammar<DerivedT>::parse<boost::spirit::scanner<>>(const ScannerT &) const' being compiled
       with
       [
           DerivedT=my_grammar,
           ScannerT=boost::spirit::scanner<>
       ]
       d:\prog\boost_1_36_0\boost\spirit\home\classic\core\impl\parser.ipp(47) : see reference to function template instantiation 'boost::spirit::parse_info<IteratorT> boost::spirit::parse<const CharT*,DerivedT>(const IteratorT &,const IteratorT &,const boost::spirit::parser<DerivedT> &)' being compiled
       with
       [
           IteratorT=const char *,
           CharT=char,
           DerivedT=my_grammar
       ]
       c:\documents and settings\anders\my documents\visual studio 2005\projects\spiritclosuretest\spiritclosuretest\spiritclosuretest.cpp(54) : see reference to function template instantiation 'boost::spirit::parse_info<IteratorT> boost::spirit::parse<char,DerivedT>(const CharT *,const boost::spirit::parser<DerivedT> &)' being compiled
       with
       [
           IteratorT=const char *,
           DerivedT=my_grammar,
           CharT=char
       ]


Source:

#include <boost/spirit.hpp>
#include <boost/spirit/phoenix/primitives.hpp>
#include <iostream>

struct result_closure : boost::spirit::closure<result_closure, int, int>
{
  member1 res1;
  member2 res2;
};

struct my_grammar : boost::spirit::grammar<my_grammar>
{
  template <typename ScannerT>
  struct definition
  {
     explicit definition(const my_grammar& self)
     {
        using boost::spirit::ch_p;
        using boost::spirit::uint_p;
        using phoenix::var;
        using phoenix::arg1;
        using phoenix::arg2;

        exp
           = uint_p[exp.res1 = arg1] >> ch_p('-') >> uint_p[exp.res2 = arg1]
           ;

        root
           = exp[var(self.i) = arg2] // compiler error here if using arg2.
           ; // arg1 works fine though.
     }

     boost::spirit::rule<ScannerT, result_closure::context_t> exp;
     boost::spirit::rule<ScannerT> root;

     const boost::spirit::rule<ScannerT>& start() const
     {
        return root;
     }
  };

  my_grammar(int& i_)
   : i(i_)
  {
  }

  int& i;
};

int main()
{
  int i;
  my_grammar g(i);
  if (parse("1-2", g).full)
  {
     std::cout << i << "\n";
  }
}