Are C++ templates a precompiler thing?

J

JohnQ

Well apparently not since one can step thru template code with a debugger.
But if I was willing to make the concession on debugging, templates would be
strictly a precompiler thing? I have a feeling the answer I'm going to get
back will be "no, because templates have taken on a life of their own since
their original conception and now also affect compiler implementation"
(read: not good, IMO.

John
 
I

Ian Collins

JohnQ said:
Well apparently not since one can step thru template code with a debugger.
But if I was willing to make the concession on debugging, templates would be
strictly a precompiler thing? I have a feeling the answer I'm going to get
back will be "no, because templates have taken on a life of their own since
their original conception and now also affect compiler implementation"
(read: not good, IMO.
There isn't a precompiler.

No, if they were, they would suffer from the same drawbacks as macros,
such as file only scope and lack of type safety.
 
R

Robbie Hatley

JohnQ said:
Are C++ templates a precompiler thing?

By "precompiler", I presume you mean the C/C++ preprocessor?
That's not *any* kind of "compiler", pre-, post-, or otherwise.
It's just a text editor.

Templates are a part of the C++ language. They are not
preprocessor macros. If you want to use preprocessor macros
(and there's no reason not to), use "#define", not "template".

I, for one, love macros. And templates. I use both all the
time. But they're not even remotely similar. One is a
text-editing command; the other is a system for building
functions or classes which can use data of generic type.
The type needs to be decided-on before compile time, yes;
but templates remove the necessity of writing the same code
37 times just to handle 37 different data types.

Just try re-implimenting a container -- say, a binary tree --
for a bunch of different data types, and you'll quickly
appreciate the value of templates. (And you'll see that
macros are of no use for that purpose.)
 
J

JohnQ

Robbie Hatley said:
By "precompiler", I presume you mean the C/C++ preprocessor?
That's not *any* kind of "compiler", pre-, post-, or otherwise.
It's just a text editor.

Templates are a part of the C++ language. They are not
preprocessor macros.

Can they be implemented that way though (early work did exactly that).
If you want to use preprocessor macros
(and there's no reason not to), use "#define", not "template".

What's the diff?
I, for one, love macros. And templates. I use both all the
time. But they're not even remotely similar.

I disagree. I'm leaning toward "they should be the same". Beyond that
(macros), templates become unwieldly.
One is a
text-editing command; the other is a system for building
functions or classes which can use data of generic type.
The type needs to be decided-on before compile time, yes;
but templates remove the necessity of writing the same code
37 times just to handle 37 different data types.

Just try re-implimenting a container -- say, a binary tree --
for a bunch of different data types, and you'll quickly
appreciate the value of templates. (And you'll see that
macros are of no use for that purpose.)

Again, I whole-heartedly disagree. (Yeah, I've implemented those kinds of
things).

John
 
G

Gianni Mariani

JohnQ wrote:
....
I'm not convinced that is true. Are you saying that macros can't be
type-safe?

Macros can't be chosen by type of parameter line a function can.
 
G

Gianni Mariani

JohnQ said:
Can they be implemented that way though (early work did exactly that).

If you refer to cfront then that's not true. The output from cfront
just used C as the "assembler".
What's the diff?

This is a cute piece of code - do this with macros.

=======================================================================

// ======== GroupRangeDefine ==========================================
/**
* This is used in the specializations of the GroupTypeData template
* below. It contains the specification of the beginning of the
* range as specified in the dxf file.
*/

template <
int w_From,
int w_To,
typename w_ExternalType,
typename w_InternalType = w_ExternalType,
bool w_skip_white = false
class GroupRangeDefine
{
public:

enum {
e_From = w_From,
e_To = w_To
};


// ======== Traits ================================================
/**
* This defines the traits for this group.
*
*/

class Traits
{
public:
enum { SkipWhiteSpace = false };
typedef w_ExternalType t_ExternalType;
typedef w_InternalType t_InternalType;
};


typedef Traits t_Traits;

typedef typename GroupSemanticData<w_From>::t_SemanticTraits
t_SemanticTraits;
};



// ======== GroupTypeData =============================================
/**
* GroupTypeData scans recursively through the types looking for
* the specialization that corresponds to the w_GroupCode parameter.
* This is done so that the specifications for the group type data
* correspond in a 1:1 fashion with the dxf spec. This makes the
* compiler fill in all the blanks and hence less tedious or
* error prone.
*/

template <int w_GroupCode>
class GroupTypeData
{
public:

enum {
e_From = GroupTypeData<w_GroupCode-1>::e_From,
e_To = GroupTypeData<w_GroupCode-1>::e_To
};

typedef
typename at::TypeSelect<
(e_To < w_GroupCode),
GroupTraits_Undefined,
typename GroupTypeData said:
>::w_Type
t_Traits;

typedef
typename GroupSemanticData<w_GroupCode>::t_SemanticTraits
t_SemanticTraits;
};


// specializations based on dxf documentation for "AutoCAD 2007 - March
2006"
template <> class GroupTypeData< 0 > : public GroupRangeDefine< 0, 9,
std::string > {}; // String
template <> class GroupTypeData< 10 > : public GroupRangeDefine< 10, 39,
double > {}; // Double precision 3D point value
template <> class GroupTypeData< 40 > : public GroupRangeDefine< 40, 59,
double > {}; // Double-precision floating-point value
template <> class GroupTypeData< 60 > : public GroupRangeDefine< 60, 79,
at::Int16 > {}; // 16-bit integer value
template <> class GroupTypeData< 90 > : public GroupRangeDefine< 90, 99,
at::Int32 > {}; // 32-bit integer value
template <> class GroupTypeData< 100 > : public GroupRangeDefine< 100,
100, std::string > {}; // String (255-character maximum; less for
Unicode strings)
template <> class GroupTypeData< 102 > : public GroupRangeDefine< 102,
102, std::string > {}; // String (255-character maximum; less for
Unicode strings)
template <> class GroupTypeData< 105 > : public GroupRangeDefine< 105,
105, std::string > {}; // String representing hexadecimal (hex) handle value
template <> class GroupTypeData< 110 > : public GroupRangeDefine< 110,
119, double > {}; // Double precision floating-point value
template <> class GroupTypeData< 120 > : public GroupRangeDefine< 120,
129, double > {}; // Double precision floating-point value
template <> class GroupTypeData< 130 > : public GroupRangeDefine< 130,
139, double > {}; // Double precision floating-point value
template <> class GroupTypeData< 140 > : public GroupRangeDefine< 140,
149, double > {}; // Double precision scalar floating-point value
template <> class GroupTypeData< 170 > : public GroupRangeDefine< 170,
179, at::Int16 > {}; // 16-bit integer value
template <> class GroupTypeData< 210 > : public GroupRangeDefine< 210,
239, double > {}; // Double-precision floating-point value
template <> class GroupTypeData< 270 > : public GroupRangeDefine< 270,
279, at::Int16 > {}; // 16-bit integer value
template <> class GroupTypeData< 280 > : public GroupRangeDefine< 280,
289, at::Int16 > {}; // 16-bit integer value
template <> class GroupTypeData< 290 > : public GroupRangeDefine< 290,
299, at::Int8, bool > {}; // Boolean flag value
template <> class GroupTypeData< 300 > : public GroupRangeDefine< 300,
309, std::string > {}; // Arbitrary text string
template <> class GroupTypeData< 310 > : public GroupRangeDefine< 310,
319, BinaryXdata, std::string > {}; // String representing hex value of
binary chunk
template <> class GroupTypeData< 320 > : public GroupRangeDefine< 320,
329, BinaryXdata, std::string > {}; // String representing hex handle value
template <> class GroupTypeData< 330 > : public GroupRangeDefine< 330,
369, std::string > {}; // String representing hex object IDs
template <> class GroupTypeData< 370 > : public GroupRangeDefine< 370,
379, at::Int16 > {}; // 16-bit integer value
template <> class GroupTypeData< 380 > : public GroupRangeDefine< 380,
389, at::Int16 > {}; // 16-bit integer value
template <> class GroupTypeData< 390 > : public GroupRangeDefine< 390,
399, std::string > {}; // String representing hex handle value
template <> class GroupTypeData< 400 > : public GroupRangeDefine< 400,
409, at::Int16 > {}; // 16-bit integer value
template <> class GroupTypeData< 410 > : public GroupRangeDefine< 410,
419, std::string > {}; // String
template <> class GroupTypeData< 420 > : public GroupRangeDefine< 420,
429, at::Int32 > {}; // 32-bit integer value
template <> class GroupTypeData< 430 > : public GroupRangeDefine< 430,
439, std::string > {}; // String
template <> class GroupTypeData< 440 > : public GroupRangeDefine< 440,
449, at::Int32 > {}; // 32-bit integer value
template <> class GroupTypeData< 450 > : public GroupRangeDefine< 450,
459, at::Int32 > {}; // Long
template <> class GroupTypeData< 460 > : public GroupRangeDefine< 460,
469, double > {}; // Double-precision floating-point value
template <> class GroupTypeData< 470 > : public GroupRangeDefine< 470,
479, std::string > {}; // String
template <> class GroupTypeData< 999 > : public GroupRangeDefine< 999,
999, std::string > {}; // Comment (string)
template <> class GroupTypeData< 1000 > : public GroupRangeDefine< 1000,
1009, std::string > {}; // String (same limits as indicated with 0-9
code range)
template <> class GroupTypeData< 1010 > : public GroupRangeDefine< 1010,
1059, double > {}; // Double-precision floating-point value
template <> class GroupTypeData< 1060 > : public GroupRangeDefine< 1060,
1070, at::Int16 > {}; // 16-bit integer value
template <> class GroupTypeData< 1071 > : public GroupRangeDefine< 1071,
1071, at::Int32 > {}; // 32-bit integer value
template <> class GroupTypeData< -5 > : public GroupRangeDefine< -5, -5,
std::string > {}; // APP: persistent reactor chain
template <> class GroupTypeData< -4 > : public GroupRangeDefine< -4, -4,
std::string > {}; // APP: conditional operator (used only with ssget)
template <> class GroupTypeData< -3 > : public GroupRangeDefine< -3, -3,
BinaryXdata, std::string > {}; // APP: extended data (XDATA) sentinel
(fixed)
template <> class GroupTypeData< -2 > : public GroupRangeDefine< -2, -2,
std::string > {}; // APP: entity name reference (fixed)


=======================================================================

This code allows the mapping of an int to type. This made the parsing
of dxf files a piece of cake. This can be used in a table or directly
in code and is basically a simple transformation from the dxf
documentation making the dxf parser easy to write from this point. I
don't think you can remotely do this with macros as they stand today.
After having written this DXF parser, I have yet to find a file that it
can't parse which is more than I can say for some commercial code I've
used. The neat thing is that it took me less time to write the parser
than it did trying to fix the previous version simply because I can
model the code to fit the specification closer that I could in C.

Can you create a macro to tell you if a type converts to another type or
if a type has a particular member or change behaviour of a function
template for a specific type (I call this the C++ come-from).
I disagree. I'm leaning toward "they should be the same". Beyond that
(macros), templates become unwieldly.

Templates do have a learning curve. You do have to think of your code
in a more generic fashion.

....

Again, I whole-heartedly disagree.

That you disagree is great. Don't stop there, do tell us of your reasoning.
 
D

Dizzy

JohnQ said:
Can they be implemented that way though (early work did exactly that).

Yes, _earlier_. But also back in that time they had less semantics that ISO
C++ templates have.
What's the diff?

For one you write "#define" and for the other you write "template". Or be
more specific about your question.
I disagree. I'm leaning toward "they should be the same". Beyond that
(macros), templates become unwieldly.

Any reasons why "they should be the same"? There are a lot of semantic
differences ATM. templates are dealt with at compile time by the compiler
which is after the preprocessor has ran. Much of their semantics depend on
compiler only knowledge (such as types to deduce function template
parameters, evaluation of constant expressions at compile time, SFINAE
functionality, template names are part of the C++ compile time name system
thus working with the rules of Koening lookup and the namespace composition
and importing semantics, etc).

How would you implement something like SFINAE in the preprocessor?
Again, I whole-heartedly disagree. (Yeah, I've implemented those kinds of
things).

I seriously doubt your implementation supports SFINAE, ADL and template
parameter deduction for function templates.
 
J

JohnQ

Ian Collins said:
How can they be? They are simple text substitutions.

But the text can expand to type-safe code (the same as C++ templates do).
You'll get an error at compile time if you try to pass a wrong type into a
function, for example. I don't see any difference whether templates are
implemented via the preprocessor or the compiler in regards to type safety.

John
 
J

JohnQ

Gianni Mariani said:
If you refer to cfront then that's not true. The output from cfront just
used C as the "assembler".

HP hacked a preprocessor (PCC) to provide probably the earliest template
implementation for C++.
This is a cute piece of code - do this with macros.

[example omitted}

I don't have a need to do that though. If you need to, then yeah, you may
wanna use the highly complex C++ templates.
Can you create a macro to tell you if a type converts to another type or
if a type has a particular member or change behaviour of a function
template for a specific type (I call this the C++ come-from).


If I just need to create containers and that is my only interest in using
templates, the specialized stuff you're doing is, well specialized!
Templates do have a learning curve. You do have to think of your code in
a more generic fashion.

Just containers thank you.
That you disagree is great. Don't stop there, do tell us of your
reasoning.

I limit what templates can do by requiring of them that they can be
implemented simply.

John
 
J

JohnQ

Dizzy said:
Yes, _earlier_. But also back in that time they had less semantics that
ISO
C++ templates have.

That's a good thing if you ask me though: "keeping them on a leash".
For one you write "#define" and for the other you write "template". Or be
more specific about your question.

Template functionality (not the complex C++ incarnation of them) can be
implemented in various ways.
Any reasons why "they should be the same"?

Reduction of complexity.
There are a lot of semantic
differences ATM. templates are dealt with at compile time by the compiler
which is after the preprocessor has ran. Much of their semantics depend on
compiler only knowledge (such as types to deduce function template
parameters, evaluation of constant expressions at compile time, SFINAE
functionality, template names are part of the C++ compile time name system
thus working with the rules of Koening lookup and the namespace
composition
and importing semantics, etc).

How would you implement something like SFINAE in the preprocessor?

Maybe I don't need that.
I seriously doubt your implementation supports SFINAE, ADL and template
parameter deduction for function templates.

I don't think I need that.

John
 
G

Gianni Mariani

JohnQ said:
I'm not sure what you mean. Show me.

void write( int a )
{
ptintf( "%dZ", a );
}

void write( const char * str )
{
printf( "%s", str );
}


#define write( A ) printf( ???? );
 
I

Ian Collins

JohnQ said:
But the text can expand to type-safe code (the same as C++ templates do).
You'll get an error at compile time if you try to pass a wrong type into a
function, for example. I don't see any difference whether templates are
implemented via the preprocessor or the compiler in regards to type safety.
OK, show us a map container implemented as macros.
 
G

Gianni Mariani

JohnQ wrote:
....
If I just need to create containers and that is my only interest in using
templates, the specialized stuff you're doing is, well specialized!

It's just an example of a problem that has been solved many times and it
degenerates into alot of tedious code. This is a case where templates
simplify the code dramatically, if you know how to use them. The code
in this case is a simple transformation from the specification.
Just containers thank you.

Containers now, then smart pointers, special iterators etc etc. It's a
powerful tool if you learn to use it.
I limit what templates can do by requiring of them that they can be
implemented simply.

That's a "reason" ?
 
J

JohnQ

Ian Collins said:
OK, show us a map container implemented as macros.

That's not necessary. I refer you to early template implementations that
used generic.h. Once the preprocessor substitutes the type text into the
"macro" ("macro" is a somewhat inappropriate usage of the term when using
the preprocessor this way), a type-safe class exists and that is what gets
compiled. I think you are probably thinking about implementations that are
not templates (of any kind) but rather constructs based upon
pointers-to-void* ("C-style" containers/algos).

John
 
I

Ian Collins

JohnQ said:
That's not necessary. I refer you to early template implementations that
used generic.h. Once the preprocessor substitutes the type text into the
"macro" ("macro" is a somewhat inappropriate usage of the term when using
the preprocessor this way), a type-safe class exists and that is what gets
compiled. I think you are probably thinking about implementations that are
not templates (of any kind) but rather constructs based upon
pointers-to-void* ("C-style" containers/algos).
I ask again, show us a map container implemented with macros, time to
put up or shut up.
 
J

JohnQ

Gianni Mariani said:
void write( int a )
{
ptintf( "%dZ", a );
}

void write( const char * str )
{
printf( "%s", str );
}


#define write( A ) printf( ???? );

Well you're trying to come up with a macro to do the work. Of course that
won't work. You have to use the text-substitution capability of the
preprocessor to do basically what the template processor in the C++ compiler
does. There's a distinct difference and that's why those
text-substitution-patterns ("templates") , when implemented with the
preprocessor, should not be called macros (just call them "templates" or to
distinguish between them and C++ compiler tempates, "preprocessor
templates"!).

(Using printf() was a bad example though because the format specifier
changes based upon the type. You'd have to use C++ IO with overloaded
operators even with C++ compiler templates to achieve a basic template for
the above case).

Below is the general concept of using the preprocessor for templates:

(Class functions just for illustration cuz the data members in a real
implementation would probably be public. Functions can be used to
get or set. obj does not have to be a pointer.)

#define concat2(x,y) x##y
#define slink(T) concat2(slink_,T)

// The "template" below is not a "macro" (well it is, but it isn't)
// (it's just a code generator).
//
#define DeclareSLink(T)\
class slink(T)\
{\
T* obj;\
slink(T)* next;\
\
public:\
void slink(T)(T* o, slink(T)* nxt=0)\
:eek:bj(o), next(nxt) {}\
\
T*& Obj(){ return obj; } \
slink(T)*& Next(){ return next; }\
};

Usage example (declare a link class of type int and instantiate one, then
use it):

DeclareSLink(int)
int x;
slink(T) my_link(&x); // type safe
int* obj = my_link.Obj(); // type safe


Do you see anything not type-safe in the above?

John
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top