Advertisement

"Conditional" compilation.

Started by June 05, 2000 01:17 PM
11 comments, last by MadKeithV 24 years, 6 months ago
( or, "Mad Keith whines again!" ) I''ve been playing around with templates a LOT the past few days. I like them. They are a good thing. To demonstrate how crazy they are getting, this is a line from one of my latest files:

typedef TGL_Vertex< float, 3, 
                    float, 3, 
                    float, 4,
                    float, 2, 
                    standard_buffer_size
                  > CGL_Vertex3f;
 
Looks horrific, right? I''m still not happy. I''d like to do "Conditional" templates, but I''m not sure it''s possible. It would be such a nice feature! Imagine something simple (hmm, simple? ME??) like this:

template< class vector_type, int vector_dimension, class texcoord_type, int texcoord_dimension>
class TVertex
{
public:
// some stuff here
protected:
// more stuff here
private:
vector_type m_vector[vector_dimension];
#if (texcoord_dimension > 0)
texcoord_type m_texcoord[texcoord_dimension];
#endif
}
 
This doesn''t work. I believe it doesn''t generate a compiler error, but it does not use the correct value for texcoord_dimension in the #if macro - thereby not generating the right code for the template class. It''s only a simple example, but you can imagine how it can help with complex, often-changing classes. Is there a way to do this? Or am I dreaming again :-) #pragma DWIM // Do What I Mean! ~ Mad Keith ~
It's only funny 'till someone gets hurt.And then it's just hilarious.Unless it's you.
I don't know anything about templates, but I do know that #if statements won't work with variables, since variables are variable, and can change at (almost) any time. You can only do #if's on constant values, and a variable is not a constant value

It is a nice idea, but to do it you need something more advanced than the #if macro and conditional compilation.

/. Muzzafarath
Mad House Software

Edited by - Muzzafarath on June 5, 2000 2:48:51 PM
I'm reminded of the day my daughter came in, looked over my shoulder at some Perl 4 code, and said, "What is that, swearing?" - Larry Wall
Advertisement
The thing is, it''s not really a variable!

I can use it to initialise the size of a static array - that means C++ interprets it as a constant. However, the preprocessing order makes it so that the macro doesn''t get the template value of that particular symbol, but just takes any odd number.

I could use #define TEXCOORD_DIMENSION somevalue, and then #undef it again, but that''s such old syntax, and in order to make it work, the person using the template has to know which macros to define. (Cfr. the Mesa3D source code)

I guess maybe I should write to Soustrop!

something else that could be fun is template definitions like this:
 template< class T, int dimension = 3>  

Default template arguments! I haven''t tried this yet, so it might actually work, but most likely doesn''t.


#pragma DWIM // Do What I Mean!
~ Mad Keith ~
It's only funny 'till someone gets hurt.And then it's just hilarious.Unless it's you.
Templates are designed to create classes that can work on arbitrary data, not to enable parameterized arbitrary class type building.

Also, AFAIK, macros are a single-pass precompile operation - the aren''t conditionally parsed with code. I.e., the conditional define will be looked at by the precompiler once, and then the compiler will proceed as normal.

If you want to have the option to define a non-textured vertex, simply create another class - it''ll be easier to work with, and you won''t ever be wondering why you''re missing a data member because your template parameters aren''t right.
Creativity is a bloody nuisance and an evil curse that will see to it that you die from stress and alcohol abuse at a very early age, that you piss off all your friends, break appointments, show up late, and have this strange bohemian urge (you know that decadent laid-back pimp-style way of life). The truly creative people I know all live lousy lives, never have time to see you, don't take care of themselves properly, have weird tastes in women and behave badly. They don't wash and they eat disgusting stuff, they are mentally unstable and are absolutely brilliant. (k10k)
I don''t think you need the preprocessor conditionals for templates. Any optimizing compiler would strip out the impossible-to-reach code ie;

template MyClass::MyFunction()
{
if ( alpha > 100 )
{
// Do something
}
else
{
// Do something else
}
}

...a call to MyClass<200>::MyFunction() would result in the following code being generated (I believe code is generated for each different template parameter instantiation):

if( 200 > 100)
{
// Do something
}
else
{
// Do something else
}

...any decent optimizing compiler will reduce this to:

// Do something

...so effectively the if-statement becomes a kind of #if preprocessor conditional in the special case of template parameters.

Hope this is right and hope it helps.

Karen






Urk...the last post ate my less-than/greater-than symbols after template...I''ll use ''['' instead. So the function definition should be:

template [int] MyClass[int alpha]::MyFunction()

Sorry about that,
Karen
Advertisement
The reason that:

#if (texcoord_dimension > 0)
texcoord_type m_texcoord[texcoord_dimension];
#endif

does not work like you expect is becuase #if indicates a procompiler directive. When you compile your program, the precompiler runs first, and when it gets to

#if (texcoord_dimension > 0)

it checks to see if (texcoord_dimension > 0) has been defined with the precompiler directive #define, because this is a variable, it has not been defined, thus the line after the #if

texcoord_type m_texcoord[texcoord_dimension];

is ommited from the file. Next the file, without

texcoord_type m_texcoord[texcoord_dimension];

is sent to the compiler, so its like this like is not even there.
The reason that:

#if (texcoord_dimension > 0)
texcoord_type m_texcoord[texcoord_dimension];
#endif

does not work like becuase '#' indicates a procompiler directive. When you compile your program, the precompiler runs first, and when it gets to

#if (texcoord_dimension > 0)

it checks to see if '(texcoord_dimension > 0)' has been defined with the precompiler directive #define. Because this is a variable, it has not been defined, thus the line after the #if

texcoord_type m_texcoord[texcoord_dimension];

is ommited from the file. Next the file, without

texcoord_type m_texcoord[texcoord_dimension];

is sent to the compiler, so its like this like is not even there.

Edited by - Enix on June 5, 2000 5:50:50 PM
Ahh, such interesting posts that detail my exact thought process before I posted this question

I knew it would get thoughts rolling!
1. "texcoord_dimension" is NOT a variable. If it was, it would be illegal to declare an array like int blah[texcoord_dimension] in my class, and that''s perfectly possible.

2. Yes, the precompiler is a single-pass thing, per source file, NORMALLY, but not for header files. The template is declared in a header, and the header is included in your source file when you need it. For an example of this, look at the Mesa3D source code, the triangle rasterisers. They have a #define based C template in a header file, and it is included multiple times in the same source file, to different effect each time because the macros in the header file are redefined each time. So that''s why I thought it COULD be possible to use #if.

3. #if doesn''t work. Don''t ask me why, I can''t explain it, but it''s not all that unexpected. It probably has to do with the way templates are parsed, and what kind of constructs the template parameters are internally. Most likely, they are invisible to the preprocessor, so the condition is always false.
I guess I could look it up in the C++ specs, but that would be more effort than it''s worth . I don''t want to use preprocessor macros!

4. Relying on the compiler to optimise. I have thought about this. The only problem is that I can''t force it to strip a class member using that method. I can''t put an if-statement into a class declaration.

Oh well, I guess I''m just sick trying to do these things using templates! It would just be handy because I''ll have to change those vertex classes too damn often for it to be fun to rewrite the class constantly.


#pragma DWIM // Do What I Mean!
~ Mad Keith ~
It's only funny 'till someone gets hurt.And then it's just hilarious.Unless it's you.
[steams with rage]

There is a way to do all of this, using the C++ standard...
It''s great, you can do really amazing things, like emulate macros using function templates, overload template classes, partially specialise template classes...

So why am I steaming with rage?

[snippet from MSDN]
INFO: C++ Standard Noncompliance Issues with Visual C++ 6.0

Partial ordering of template functions (14.5.5.2) not supported.
Q240869 BUG: C2667 and C2668 on Partial Ordering of Function Templates

Template arguments must be deduced for function templates (14.8.1).
Q240871 BUG: Explicitly Specified Template Functions Not Overloaded Correctly

Class template partial specializations (14.5.4) not supported.
Q240866 BUG: C2989 and C2988 on Class Template Partial Specializations

....

the list is a lot longer than that, and 70% of the bugs ALL have to do with the wonderful things you SHOULD be able to do with templates...

BUGGER!

I wish there was a better implementation of the C++ standard around with a decent compiler..


#pragma DWIM // Do What I Mean!
~ Mad Keith ~
It's only funny 'till someone gets hurt.And then it's just hilarious.Unless it's you.

This topic is closed to new replies.

Advertisement