Boost logo

Boost Users :

From: Martin Apel (martin.apel_at_[hidden])
Date: 2008-06-17 03:04:14


Joel de Guzman wrote:
>> While trying to generate a small example, I found out, what is
>> causing the problem:
>> I marked the grammar class using the closure with
>> __declspec(dllexport), which causes MSVC to instantiate all members
>> of a template,
>> even if they are never needed. It seems that otherwise the "context"
>> member function is never instantiated.
>> If you remove the __declspec(dllexport), everything compiles. I still
>> think, that the code is wrong, because it returns a pointer, where it
>> should return a reference. I have attached a small example, which
>> triggers the problem.
>
> No it is not. You can return a reference to a pointer. Example:
>
> char const*& foo()
> {
> static char const* s = "hi";
> return s;
> }
>
I know, that you can return a reference to a pointer. But in
boost/spirit/phoenix/closures.hpp closure<..>::context() is declared to
return a reference to a closure_frame_t, which is a closure_frame<self_t>.
The implementation consists of frame.get(), which invokes the get method
on holder_t, which is a closure_frame_holder<closure_frame_t>. When
looking at the get method of closure_frame_holder, it
returns a reference to frame_ptr, which is a frame_t*, which is not the
same as an object of type closure_frame<self_t> as declared by
closure<...>::context()
>> By the way, the example implements a real parser, which uses the
>> standard C++ runtime to convert the real number into a double. I had
>> to implement this,
>> because I found out, that the Spirit real_p parser creates
>> numerically different results from the standard runtime, i.e.
>> parsing the string "1.8" delivers a number like 1.8000000532 using
>> Spirit, while the C++ runtime delivers something like 1.7999999973,
>> which is always closer
>> to the real value. Please note, that these numbers are not accurate,
>> they are simply meant to demonstrate, what I mean.
>
> Wow, that's a strong accusation ;-) Again, code please. I can't
> seem to reproduce your result:
>
> parse("1.8", real_p[assign_a(d)]);
> std::cout.setf(std::ios::fixed|std::ios::left);
> std::cout.precision(15);
> std::cout << d << std::endl;
>
> gives me:
>
> 1.800000000000000
>
> Hmmm... how about:
>
> parse("1.800000000000001", real_p[assign_a(d)];
>
> gives me:
>
> 1.800000000000001
Sorry, it wasn't meant as an accusation. I had found this out some
months ago, so I tried to give an example from my memory. I didn't
expect Spirit to behave exactly as iostream, because there was no
specification with respect to numerical accuracy. Additionally I only
found this out, when setting the precision to 20, 15 is not enough. I
played around a bit, to find an example:
#include <string>
#include <sstream>
#include <iostream>
#include <boost/spirit/core.hpp>
#include <boost/spirit/actor.hpp>

int main(void)
{
   using namespace std;
   using namespace boost::spirit;

   double d;
   string s("0.6");
   parse(s.begin(), s.end(), real_p[assign_a(d)]);
   cout.setf(std::ios::fixed|std::ios::left);
   cout.precision(20);
   cout << "Parsing with Spirit gives: " << d << endl;

   stringstream stream(s);
   double std_result;
   stream >> std_result;
   std::cout << "Parsing with iostream gives: " << std_result << endl;
}

results in the following in my machine:
Parsing with Spirit gives: 0.60000000000000008882
Parsing with iostream gives: 0.59999999999999997780

Hope this helps,

Regards,

Martin


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net