|
-
January 8th, 2003, 03:05 AM
#1
HELP! templates with a 'double' parameter
Hi, try and run the following code. An explanation:
I have two template classes for the test: D and I which are defined by 3 double/integer parameters.
I've put a printf call in their ctor to see the parameter values.
In main(), I try to create several objects of D and I. And as you will run this code, you'll see that each behaves really weird. For example:
D<1,0,0>, D<-1,0,0> and D<2,0,0> give the same output: 1,1,1 , but D<3,0,0> gives the correct output: 3,0,0. If you change d1 to, say, D<5,0,0>, then d1,d2 and d3 will all give output: 5,0,0! It's as if d1..d3 are initialized with the same template instance, but d4 isn't!!! why!?!?!?
D<20,0,0> and D<-20,0,0> give the same output: 20,0,0.
The 'I' objects seem to be OK with any value.
Anyway, look for yourselves. WHAT IS GOING ON HERE?
And the weirdest one of all: try running it in the debugger, put a breakpoint on the 'printf' and as soon as you get there, take a look at the 'Context' combo box in VStudio. See what happens when you reach d4 and continue....
Note: I even tried to work with 'float' instead of 'double', since it's only 32 bits (I thought it may have sth to do with it). No change.
template <double x, double y, double z>
class D
{
public: D() { printf("%f %f %f\n", x,y,z); }
};
template <int x, int y, int z>
class I
{
public: I() { printf("%d %d %d\n", x,y,z); }
};
int main(int argc, char* argv[])
{
D<1.0,0,0> d1;
D<-1.0,0,0> d2;
D<2.0,0,0> d3;
D<20.0,0,0> d4;
D<(-20.0),0,0> d5;
D<0,10,0> d6;
D<0,-3.0,0> d7;
D<0,-10.0,0> d8;
I<1,0,0> i1;
I<-1,0,0> i2;
I<0,-10,0> i3;
I<0,10,0> i4;
return 0;
}
-
January 8th, 2003, 04:51 AM
#2
templates vs. the compiler
I could probably be enticed to place money on the bet that you are using Microsoft's Visual C++. If this is truly the case, then check out Knowledge Base Article 240871. Although I haven't seen this problem pop up in exactly the form you have stated, it seems likely that what you are doing is another instance of this oft-bereaved problem with VC++'s name mangling / lookup methods...
*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/
"It's hard to believe in something you don't understand." -- the sidhi X-files episode
galathaea: prankster, fablist, magician, liar
-
January 8th, 2003, 05:02 AM
#3
by the way...
I've tried to compile with GNU, and it appears that it doesn't allow 'float' parameters.... so it's either a bug or a non-compliance issue (which should be documented if I ever find where!!!)
-
January 8th, 2003, 05:58 AM
#4
Template parameters defined as doubles is non-standard. Here it is from the ANSI/ISO specification, 14.1.4:
A nontype template parameter shall have one of the following (optionally cv-qualified)
types:
— integral or enumeration type,
— pointer to object or pointer to function,
— reference to object or reference to function,
— pointer to member.
So the code you posted is not even supposed to compile. Also, the template instantiation must have integral argument types. Therefore your instantiations are illegal also.
Regards,
Paul McKenzie
-
January 8th, 2003, 06:37 AM
#5
just as I thought...
But it DID comile in VC++. That's exactly the problem (Their problem). But it's ok, I now know that it's a bug, since it doesn't compile under GNU.
-
January 8th, 2003, 02:19 PM
#6
WRONG!!!!
WRONGWRONGWRONGWRONGWRONG!!!
I was wrong on this one. It was way too late for me and I missed entirely the real point. Paul is correct here. Its not a proper non-type parameter. Sorry for the misinfo... (glad I didn't have any money riding).
*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/
"It's hard to believe in something you don't understand." -- the sidhi X-files episode
galathaea: prankster, fablist, magician, liar
-
January 8th, 2003, 11:22 PM
#7
I can remember that I encountered the same problem in a small project last year. At that time I didn't know that template params defined as double was non-standard.
My "solution" was to create a template called something like Tdouble:
Code:
template <int Q, int E>
struct Tdouble
{
static double value()
{
static const double val = pow(10.0, (double)E) * (double)Q;
return val;
}
};
This way I could use my original design with minimal changes. In your example you could then write something like this:
Code:
template <class X, class Y, class Z >
struct D
{
D()
{
cout.precision(10);
cout << "x: " << X::value() << "\n"
<< "y: " << Y::value() << "\n"
<< "z: " << Z::value() << "\n"
<< endl;
}
};
typedef D< Tdouble<1,0>, Tdouble<0,0>, Tdouble<0, 0> > d1;
typedef D< Tdouble<-1,0>, Tdouble<0,0>, Tdouble<0, 0> > d2;
typedef D< Tdouble<2,0>, Tdouble<0,0>, Tdouble<0, 0> > d3;
typedef D< Tdouble<20,0>, Tdouble<0,0>, Tdouble<0, 0> > d4;
typedef D< Tdouble<-20,0>, Tdouble<0,0>, Tdouble<0, 0> > d5;
typedef D< Tdouble<0,0>, Tdouble<10,0>, Tdouble<0, 0> > d6;
typedef D< Tdouble<0,0>, Tdouble<-3,0>, Tdouble<0, 0> > d7;
typedef D< Tdouble<0,0>, Tdouble<-10,0>, Tdouble<0, 0> > d8;
int main()
{
d1 da;
d2 db;
d3 dc;
d4 dd;
d5 de;
d6 df;
d7 dg;
d8 dh;
cout << "---" << endl << endl;
cout << Tdouble<123456789, -5>::value() << endl; //1234.56789
cout << Tdouble<1, -5>::value() << endl; //0.00001
cout << Tdouble<25,-2>::value() << endl; //0.25
system("pause");
return 0;
}
I know some may think this is not a nice solution, but it is at least an option that works in both VC and GNU.
Comments are welcome
-
January 13th, 2003, 01:31 AM
#8
Well...
There are a lot for ways to overcome the problem, but nm. I didn't want to use the E/Q technique, but I did figure out two optional ideas:
1. implement IEEE754SP (floating point) on a 32 integer within the class, so I'm not limited with any compiler moods :-)
2. use the integer as a fixed-point variable (you know, Lword is the fraction, Hword is the integer, and so on). Much faster.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|