[typeof][spirit][msvc gurus] is it possible to work around this bug??

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

[typeof][spirit][msvc gurus] is it possible to work around this bug??

Tobias Schwinger
Hi List,

The code below fails to compile with MSVC8 when the macro MAKE_THINGS_FAIL is defined.

I hope the code reads well enough to communicate the problem and why it would be
quite hot to get it fixed ;-).

Thanks a lot for your help,

Tobias


   #include <boost/spirit/core.hpp>
   #include <boost/typeof/typeof.hpp>

   #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
   BOOST_TYPEOF_REGISTER_TYPE(boost::spirit::anychar_parser)
   BOOST_TYPEOF_REGISTER_TEMPLATE(boost::spirit::action, 2)
   BOOST_TYPEOF_REGISTER_TEMPLATE(boost::spirit::positive, 1)

   #define an_expression +anychar_p[ a_placeholder ]

   typedef void (* fptr)(char const * from, char const * to);

   void echo(char const * from, char const * to)
   {
     // [...]
   }

   #ifndef MAKE_THINGS_FAIL

   using boost::spirit::anychar_p;

   class a_rule_parser
     : boost::spirit::parser<a_rule_parser>
   {
     fptr a_placeholder;

     struct __rule
     {
       // hide the placeholder member variable of the outer class with a static
       // variable of the same type
       static fptr & a_placeholder;

       typedef BOOST_TYPEOF( an_expression ) type;
     };

     __rule::type __expr;
   public:

     a_rule_parser(fptr placeholder)
       : a_placeholder( placeholder )
       , __expr( an_expression )
     { }

     // [...] (it's stripped down code to show a bug)
   };

   int main()
   {
     a_rule_parser x(& echo);
     return 0;
   }

   // so far, so good...

   #else

   // ...but the same code in templated form makes msvc8 do strange things


   // using boost::spirit::anychar_p;
   using namespace boost::spirit;
   // ADL doesn't seem to work, either but I could live with this problem ;-)


   template<typename T>
   class a_rule_parser_template
     : boost::spirit::parser< a_rule_parser_template<T> >
   {
     T a_placeholder;

     struct __rule
     {
       // hide the placeholder member variable of the outer class with a static
       // variable of the same type
       static T & a_placeholder;

       typedef BOOST_TYPEOF_TPL( an_expression ) type;
     };

     typename __rule::type __expr;
   public:

     a_rule_parser_template(T const & placeholder)
       : a_placeholder( placeholder )
       , __expr( an_expression )
     { }

     // [...] (it's stripped down code to show a bug)
   };

   int main()
   {
     a_rule_parser_template<fptr> x(& echo);
     return 0;
   }
   #endif

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [typeof][spirit][msvc gurus] is it possible to work around this bug??

Tobias Schwinger
Forgot something...

Tobias Schwinger wrote:

>    template<typename T>
>    class a_rule_parser_template
>      : boost::spirit::parser< a_rule_parser_template<T> >
>    {
>      T a_placeholder;
>
>      struct __rule
>      {
>        // hide the placeholder member variable of the outer class with a static
>        // variable of the same type
>        static T & a_placeholder;
>
>        typedef BOOST_TYPEOF_TPL( an_expression ) type;
Line 77  ^^
Typeof acts like a black hole in this context; the "laws of C++ physics" seem not
to apply any longer. There should be absolutely no reason for deduction to fail
like this:

   test.cpp(77) : error C2784: 'boost::spirit::positive<S> boost::spirit::operator
   +(const boost::spirit::parser<DerivedT> &)' : could not deduce template argument
   for 'const boost::spirit::parser<DerivedT> &' from 'T'
           e:\Libs\Boost\MainCVS2\boost/spirit/core/composite/positive.hpp(93) :
   see declaration of 'boost::spirit::operator +'
   test.cpp(72) : see reference to class template instantiation
   'a_rule_parser_template<T>::__rule' being compiled
   test.cpp(89) : see reference to class template instantiation
   'a_rule_parser_template<T>' being compiled
   test.cpp(77) : error C2675: unary '+' : 'T' does not define this operator or a
   conversion to a type acceptable to the predefined operator
   test.cpp(77) : error C2784: 'boost::spirit::positive<S> boost::spirit::operator
   +(const boost::spirit::parser<DerivedT> &)' : could not deduce template argument
   for 'const boost::spirit::parser<DerivedT> &' from 'T'
   e:\Libs\Boost\MainCVS2\boost/spirit/core/composite/positive.hpp(93) : see
   declaration of 'boost::spirit::operator +'
   test.cpp(77) : error C2675: unary '+' : 'T' does not define this operator or a
   conversion to a type acceptable to the predefined operator
   test.cpp(77) : error C2784: 'boost::spirit::positive<S> boost::spirit::operator
   +(const boost::spirit::parser<DerivedT> &)' : could not deduce template argument
   for 'const boost::spirit::parser<DerivedT> &' from 'T'
   e:\Libs\Boost\MainCVS2\boost/spirit/core/composite/positive.hpp(93) : see
   declaration of 'boost::spirit::operator +'
   [...] last two messages repeat several times

--
Tobias

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [typeof][spirit][msvc gurus] is it possible to work around this bug??

Arkadiy Vertleyb
"Tobias Schwinger" <[hidden email]> wrote

> Typeof acts like a black hole in this context; the "laws of C++ physics"
seem not
> to apply any longer. There should be absolutely no reason for deduction to
fail
> like this:
>
>    test.cpp(77) : error C2784: 'boost::spirit::positive<S>
boost::spirit::operator
>    +(const boost::spirit::parser<DerivedT> &)' : could not deduce template
argument
>    for 'const boost::spirit::parser<DerivedT> &' from 'T'

What's T?  There seem to be a number of contexts when some types can't be
bound to const T&.  For example VC71 can't do it from inside the template
when T is a function (see currently failig typeof test).

Regards,
Arkadiy



_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [typeof][spirit][msvc gurus] is it possible to work around this bug??

Tobias Schwinger
Arkadiy Vertleyb wrote:
> "Tobias Schwinger" <[hidden email]> wrote
>>
>>   test.cpp(77) : error C2784: 'boost::spirit::positive<S> boost::spirit::operator
>>   +(const boost::spirit::parser<DerivedT> &)' : could not deduce template argument
>>   for 'const boost::spirit::parser<DerivedT> &' from 'T'
>
>
> What's T?  

/I/ don't know what T really is (MSVC won't tell me) ;-).

T /should/ be:

    action<anychar_parser, void(*)(char const *, char const *)>

where

    template<class P, typename A> class action<P,A>

is derived from

    parser< action<P,A> >

however.

> There seem to be a number of contexts when some types can't be
> bound to const T&.  For example VC71 can't do it from inside the template
> when T is a function (see currently failig typeof test).

I had a look at the 'function_ptr_from_tpl' test and instantly changed my code to
use a functor instead of a function pointer -- with best hopes but a bad feeling
because I thought I'd tried it before...

Most unfortunately the function pointer is not the problem, here.
Same problem, except that T should now be:

   action<anychar_parser, functor>

...and MSVC still won't tell us ;-).


Thanks anyway,

Tobias


   #include <boost/spirit/core.hpp>
   #include <boost/typeof/typeof.hpp>

   #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
   BOOST_TYPEOF_REGISTER_TYPE(boost::spirit::anychar_parser)
   BOOST_TYPEOF_REGISTER_TEMPLATE(boost::spirit::action, 2)
   BOOST_TYPEOF_REGISTER_TEMPLATE(boost::spirit::positive, 1)

   #define an_expression +anychar_p[ a_placeholder ]

   struct functor
   {
     void operator()(char const * from, char const * to) const
     {
       // [...]
     }
   };
   BOOST_TYPEOF_REGISTER_TYPE(functor)

   #ifndef MAKE_THINGS_FAIL

   using boost::spirit::anychar_p;

   class a_rule_parser
     : boost::spirit::parser<a_rule_parser>
   {
     functor a_placeholder;

     struct __rule
     {
       // hide the placeholder member variable of the outer class with a static
       // variable of the same type
       static functor & a_placeholder;

       typedef BOOST_TYPEOF( an_expression ) type;
     };

     __rule::type __expr;
   public:

     a_rule_parser(functor placeholder)
       : a_placeholder( placeholder )
       , __expr( an_expression )
     { }

     // [...] (it's stripped down code to show a bug)
   };

   int main()
   {
     functor f;
     a_rule_parser x(f);
     return 0;
   }


   // so far, so good...

   #else

   // ...but the same code in templated form makes msvc8 do strange things


   // using boost::spirit::anychar_p;
   using namespace boost::spirit;
   // ADL doesn't seem to work, either but I could live with this problem ;-)


   template<typename T>
   class a_rule_parser_template
     : boost::spirit::parser< a_rule_parser_template<T> >
   {
     T a_placeholder;

     struct __rule
     {
       // hide the placeholder member variable of the outer class with a static
       // variable of the same type
       static T & a_placeholder;

       typedef BOOST_TYPEOF_TPL( an_expression ) type;
     };

     typename __rule::type __expr;
   public:

     a_rule_parser_template(T const & placeholder)
       : a_placeholder( placeholder )
       , __expr( an_expression )
     { }

     // [...] (it's stripped down code to show a bug)
   };

   int main()
   {
     functor f;
     a_rule_parser_template<functor> x(f);
     return 0;
   }
   #endif

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [typeof][spirit][msvc gurus] is it possible to work around this bug??

Arkadiy Vertleyb
"Tobias Schwinger" <[hidden email]> wrote

> Most unfortunately the function pointer is not the problem, here.
> Same problem, except that T should now be:
>
>    action<anychar_parser, functor>
>
> ...and MSVC still won't tell us ;-).

Can you take the expression whose typeof you are trying to take, and just
pass it into:

template<class T> void foo(const T&) {}

If it still fails, binding is the problem.  We will not solve the problem
this way, but we'll at least classify it...

Regards,
Arkadiy



_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [typeof][spirit][msvc gurus] is it possible to work around this bug??

Tobias Schwinger
Arkadiy Vertleyb wrote:

> "Tobias Schwinger" <[hidden email]> wrote
>
>
>>Most unfortunately the function pointer is not the problem, here.
>>Same problem, except that T should now be:
>>
>>   action<anychar_parser, functor>
>>
>>...and MSVC still won't tell us ;-).
>
>
> Can you take the expression whose typeof you are trying to take, and just
> pass it into:
>
> template<class T> void foo(const T&) {}
>

I can. I can also use a function template like

     template<typename T> int eat(T const &) { return 0; }

and

     #define an_expression eat(anychar_p[ a_placeholder ])
     // note: eat(T const &) in place of of the operator+(parser<D> const &)

and it works within Typeof.

Even better (and now things really get weird):

     #define an_expression anychar_p[ a_placeholder ] >> anychar_p
     // note: don't forget to register boost::spirit::sequence<class,class>
     // when trying this one

works. Looking at definition of operator>> in

     boost/spirit/core/composite/sequence.hpp

we see the same deduction. The only differences: it's a binary operator and
heavily overloaded (for one parser argument and the other argument being char,
wchar_t, char const *, wchar_t const *).

So I added a function like this

   template<typename U, typename V>
   int whattheheck(boost::spirit::parser<U> const &,
                   boost::spirit::parser<V> const &)
   { return 0; }

   #define an_expression whattheheck(anychar_p[ a_placeholder ],anychar_p)

and get an error.

Now when I add an overload like this:

   struct surprise { };

   template<typename U>
   int whattheheck(surprise, boost::spirit::parser<U> const &)
   { return 0; }

things work again.


> If it still fails, binding is the problem.  We will not solve the problem
> this way, but we'll at least classify it...

Well, I just found a workaround while just replying (the "cardboard programmer" [
http://tinyurl.com/9xcf7 ] effect, I guess).

The workaround isn't too pretty (especially because I still don't really
understand it) but still:

   namespace boost { namespace spirit {

       struct msvc_workaround { };
       int operator+(msvc_workaround) { return 0; }

   } }


Thanks,

Tobias

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [typeof][spirit][msvc gurus] is it possible to work around this bug??

David Abrahams
In reply to this post by Tobias Schwinger
Tobias Schwinger <[hidden email]> writes:

> Arkadiy Vertleyb wrote:
>> "Tobias Schwinger" <[hidden email]> wrote
>>>
>>>   test.cpp(77) : error C2784: 'boost::spirit::positive<S> boost::spirit::operator
>>>   +(const boost::spirit::parser<DerivedT> &)' : could not deduce template argument
>>>   for 'const boost::spirit::parser<DerivedT> &' from 'T'
>>
>>
>> What's T?  
>
> /I/ don't know what T really is (MSVC won't tell me) ;-).

have you tried instantiating an un-defined template on T?

     template <class T> struct unknown;

then instantiate

     unknown<T>

or instantiate boost::mpl::print<T> if this could happen any number of
times, to avoid stopping compilation.

--
Dave Abrahams
Boost Consulting
www.boost-consulting.com

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [typeof][spirit][msvc gurus] is it possible to work around this bug??

Tobias Schwinger
In reply to this post by Tobias Schwinger
Tobias Schwinger wrote:
>
>    namespace boost { namespace spirit {
>
>        struct msvc_workaround { };
>        int operator+(msvc_workaround) { return 0; }
>
>    } }
>

For the protocol:

Better (Spirit-specific) solution: add overloads for character & string literals
(they should be there at least for the sake of completeness).

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [typeof][spirit][msvc gurus] is it possible to work around this bug??

Tobias Schwinger
In reply to this post by David Abrahams
David Abrahams wrote:
> Tobias Schwinger <[hidden email]> writes:
>>Arkadiy Vertleyb wrote:
>>>What's T?  
>>
>>/I/ don't know what T really is (MSVC won't tell me) ;-).
>
>
> have you tried instantiating an un-defined template on T?

The only problem left is: if add code to deduce the type (to instantiate a
template on it) I still won't know what the type was in the context the compiler
failed to deduce from for absolutely non-obvious reasons ;-).

>
>      template <class T> struct unknown;
>
> then instantiate
>
>      unknown<T>
>
> or instantiate boost::mpl::print<T> if this could happen any number of
> times, to avoid stopping compilation.
>

Interesting! Never noticed mpl::print before... It must be either new or
undocumented...


Thanks,

Tobias

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [typeof][spirit][msvc gurus] is it possible to work around this bug??

Tobias Schwinger
In reply to this post by Tobias Schwinger
Tobias Schwinger wrote:

> Tobias Schwinger wrote:
>
>>   namespace boost { namespace spirit {
>>
>>       struct msvc_workaround { };
>>       int operator+(msvc_workaround) { return 0; }
>>
>>   } }
>>
>

VVVV

>
> For the protocol:
>
> Better (Spirit-specific) solution: add overloads for character & string literals
> (they should be there at least for the sake of completeness).

^^^^ nonsense (at least in this case): an arithmetic operator can't be overloaded for an arithmetic type...

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost