1 | /*
|
---|
2 | Ulrich Mutze 2016-06-23
|
---|
3 |
|
---|
4 | Title:
|
---|
5 | ------
|
---|
6 | User-defined conversion operator from a wrapper class to a
|
---|
7 | boost/multiprecision floating-point type does not compile.
|
---|
8 |
|
---|
9 | The observation:
|
---|
10 | ---------------
|
---|
11 | With the first of the two typedefs in action the file does not compile.
|
---|
12 | Commentarizing the first typedef and activating the second lets
|
---|
13 | everything work fine.
|
---|
14 | According to the rules of C++ it should work in both cases.
|
---|
15 | That it does not has probably to be considered a bug in the
|
---|
16 | boost/multiprecision class system. It conflicts with the statement
|
---|
17 | "It acts as an entirely C++ (header only and dependency free) floating-point number type that is a drop-in replacement for the native C++ floating-point types, but with much greater precision."
|
---|
18 | of the documentation to cpp_bin_float.
|
---|
19 |
|
---|
20 | The context:
|
---|
21 | -----------
|
---|
22 | In my large C++ class system ( referred to as C+- in uuu.ulrichmutze.de) which originally did not enable multiprecision, I typedefed the floating-point type to be used througout the entire code base as
|
---|
23 | typedef double (or float or long double) R;
|
---|
24 | Here R stands for the set of real numbers as used in mathematics and not
|
---|
25 | for the statistics-oriented software system R.
|
---|
26 | In developing classes to be used in physics simulations it turned out
|
---|
27 | often to be necessary to give a class an additional R-typed member.
|
---|
28 | Since the built-in types get not automatically initialized, in such a case
|
---|
29 | I had to extend the constructor initializer list in all the many constructors of my class by hand which was tedious and error-prone.
|
---|
30 | So I decided to have floating-point data members in the form
|
---|
31 | R1 x_;
|
---|
32 | with a wrapper class R1 as defined in the following code. Using x_
|
---|
33 | somewhere in an arithmetic expression would automatically convert it to R
|
---|
34 | just as I had introduced it as
|
---|
35 | R x_;
|
---|
36 | When I enabled multiprecision my first option was
|
---|
37 | typedef mpfr::mpreal R;
|
---|
38 | and everything worked well with this "drop-in replacement".
|
---|
39 | See my work:
|
---|
40 | Precision-dependent symmetry breaking in simulated motion of
|
---|
41 | polyspherical grains (2009)
|
---|
42 | http://uuu.ma.utexas.edu/mp_arc/c/09/09-113.pdf
|
---|
43 | Ironically the wrapper R1 was no longer necessary in principle since now
|
---|
44 | R-typed data members would have been initialized as R(0) automaticaly.
|
---|
45 | However, the bit of extra complexity did no harm and was still necessary
|
---|
46 | for the normal mode of my programs in which R was an alias for double.
|
---|
47 | Of course, my expectation was that replacing mpreal by any of the
|
---|
48 | boost multiprecision floating point types would work the same way. Unfortunately this turned out to be a pre-mature expectation. My hope is
|
---|
49 | that digging out the reason for this strange behavior will give hints
|
---|
50 | how the boost multiprecision floating-point types can be promoted to
|
---|
51 | real "drop-in replacements" of type double.
|
---|
52 |
|
---|
53 | The code:
|
---|
54 | ---------
|
---|
55 | */
|
---|
56 | #include <iostream>
|
---|
57 | #include <boost/multiprecision/cpp_bin_float.hpp>
|
---|
58 |
|
---|
59 | using namespace std;
|
---|
60 | using namespace boost::multiprecision;
|
---|
61 |
|
---|
62 | typedef number<cpp_bin_float<50>, et_off > R;
|
---|
63 | //typedef double R;
|
---|
64 |
|
---|
65 | //------------------------ class R1 ---------------------------------------
|
---|
66 | class R1{ // wrapper class for R
|
---|
67 | R x_;
|
---|
68 | public:
|
---|
69 | R1(void):x_(0.){}
|
---|
70 | // explicit conversion R --> R1
|
---|
71 | explicit R1(R const& a):x_(a){}
|
---|
72 | // automatic conversion operator R1 --> R
|
---|
73 | operator R()const{ return x_;}
|
---|
74 | };
|
---|
75 |
|
---|
76 | int main()
|
---|
77 | {
|
---|
78 | cout.precision(50);
|
---|
79 | R x=9.123456789123456789123456789;
|
---|
80 | R y=5.678912345678901234567890123;
|
---|
81 | R1 x1(x);
|
---|
82 | R1 y1(y);
|
---|
83 | R sum=x1+y1;
|
---|
84 | // This has to work since x1 and x2 can be converted to
|
---|
85 | // instances of R. It actually works for typedef double R;.
|
---|
86 | // My German-speaking system says for
|
---|
87 | // typedef number<cpp_bin_float<50>, et_off > R;
|
---|
88 | // 'Keine Übereinstimmung für >>operator+<< in >>x1+y1<<'
|
---|
89 | // my translation:
|
---|
90 | // 'no match for >>operator+<< in >>x1+y1<<'.
|
---|
91 | cout << " x = "<<x<<endl;
|
---|
92 | cout << " y = "<<y<<endl;
|
---|
93 | cout << " sum = "<<sum<<endl;
|
---|
94 | return 0;
|
---|
95 | }
|
---|