Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Declaring war on macros

0 views
Skip to first unread message

JKop

unread,
Apr 28, 2004, 5:29:28 AM4/28/04
to

const unsigned short int AmountHumanAdultTeeth = 32;

inline unsigned short int AddFive(unsigned short int Numbr)
{
return Numbr + 5;
}


USE THESE!!


I've heard a stupid argument before that:

#define AmountHumanAdultTeeth 32


is better because it saves memory, ie. there's no variable declared which
takes up memory.

Enlightenment time:

Upon execution, the ENTIRE program is loaded into memory, all the code for
all of the functions, all of the numbers and strings littered throughout the
code, eg.:

cout << "Hello";


are all loaded into memory. Thus, somewhere in memory you will have "Hello".

Thus, concordantly and therefore, you most certainly _are_ taking up memory
by using a macro instead of a const global variable. Furthermore, you may
even use MORE memory with a macro; For example, if you have the number "5"
littered throughout your program, you're not necessarily guaranteed that all
of the "5"'s will be taken from the same place in memory! There may be a
unique "5" in memory for every single seperate time you use it. Const global
variables are superior in EVERY WAY, BAR NONE.

As for macro functions: Similarly, there is absolutley NO JUSTIFICATION for
their use. Inline functions are superior in every way, BAR NONE!

Rolf Magnus

unread,
Apr 28, 2004, 5:59:01 AM4/28/04
to
JKop wrote:

>
> const unsigned short int AmountHumanAdultTeeth = 32;
>
> inline unsigned short int AddFive(unsigned short int Numbr)
> {
> return Numbr + 5;
> }
>
>
> USE THESE!!
>
>
> I've heard a stupid argument before that:
>
> #define AmountHumanAdultTeeth 32
>
>
> is better because it saves memory, ie. there's no variable declared
> which takes up memory.
>
> Enlightenment time:
>
> Upon execution, the ENTIRE program is loaded into memory, all the code
> for all of the functions, all of the numbers and strings littered
> throughout the code, eg.:
>
> cout << "Hello";
>
>
> are all loaded into memory. Thus, somewhere in memory you will have
> "Hello".
>
> Thus, concordantly and therefore, you most certainly _are_ taking up
> memory by using a macro instead of a const global variable.
> Furthermore, you may even use MORE memory with a macro; For example,
> if you have the number "5" littered throughout your program, you're
> not necessarily guaranteed that all of the "5"'s will be taken from
> the same place in memory! There may be a unique "5" in memory for
> every single seperate time you use it.

Actually, they might not even be taken from memory at all, or let's
better say from data memory. If you have a variable, it resides in
memory somewhere, and the compiler might need to create an instruction
that loads it from there. On assembler level that means there is an
instruction that says something like "load the value from memory
address 0xdeadbeef". If it's a macro, the literal 5 is usually directly
included in the instruction on assembler level, so the assembler
instruction would say "load the value 0x00000005". As you can see, the
instructions can be (and often are) of the same size, but in the first
case, you additionally need a memory location to save the value to (in
my example at address 0xdeadbeef). However, a constant can be used
"inline", just like the macro, so any decent compiler can also directly
put the literal 5 into the assembler instruction unless you try to take
its address, in which case the compiler needs to put it into data
memory to ensure it actually has an address. Since constants have
internal linkage by default, it would mean that each translation unit
that needs the address of the constant would need to store its own copy
of it in memory.

Anyway, in most cases, it's just not worth thinking about whether your
program will need a few bytes more. There are lots of much more
important reasons to use constants instead of macros.

> Const global variables are superior in EVERY WAY, BAR NONE.

Some would say "global variables are evil".

> As for macro functions: Similarly, there is absolutley NO
> JUSTIFICATION for their use. Inline functions are superior in every
> way, BAR NONE!

Right.

--
How come Superman could stop bullets with his chest,
but always ducked when someone threw a gun at him?

tom_usenet

unread,
Apr 28, 2004, 8:55:11 AM4/28/04
to
On Wed, 28 Apr 2004 09:29:28 GMT, JKop <NU...@NULL.NULL> wrote:

>As for macro functions: Similarly, there is absolutley NO JUSTIFICATION for
>their use. Inline functions are superior in every way, BAR NONE!

Rolf's commented on the rest of it, but I take slight issue with the
above. Inline functions are superior only when it is possible to write
an inline function to do what the macro was doing. In many cases it
isn't. (For an example of advanced usage of preprocessor macros, check
out the boost library at www.boost.org)

Tom
--
C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html

Michiel Salters

unread,
Apr 28, 2004, 10:54:28 AM4/28/04
to
JKop <NU...@NULL.NULL> wrote in message news:<YPKjc.5878$qP2....@news.indigo.ie>...

> As for macro functions: Similarly, there is absolutley NO JUSTIFICATION for
> their use. Inline functions are superior in every way, BAR NONE!

inline int BYTES_NEEDED_FOR_INTS ( int no_ints )
{
return no_ints * sizeof(int);
}
typedef char[ BYTES_NEEDED_FOR_INTS( 5 ) ] int5;

Does your compiler accept this?

Regards,
Michiel Salters

Julie

unread,
Apr 28, 2004, 11:49:44 AM4/28/04
to
JKop wrote:
[snip stuff that I don't want to comment on]

> As for macro functions: Similarly, there is absolutley NO JUSTIFICATION for
> their use. Inline functions are superior in every way, BAR NONE!

Please describe how to implement the (standard library) offsetof macro in terms
of an inline function that is 'far superior' (or at least equally inferior!).

Julie

unread,
Apr 28, 2004, 11:52:43 AM4/28/04
to

Do you consider:

#if defined (CODE_1)
// some code
#else if defined (CODE_2)
// other code
#endif

the use of macros?

Siemel Naran

unread,
Apr 28, 2004, 12:48:58 PM4/28/04
to
"Rolf Magnus" <rama...@t-online.de> wrote in message
news:c6nv60$gr1$03$1@news.t-
> JKop wrote:

Very good answer. In my experience it is very rare to use address of a
constant, such as these:

const double pi=3.14159265358979323846;


namespace physics
{

const double hbar=1.054572590e-34; // Joule*second
const double hbarsquared=1.112123347e-68; // (Joule*second)^2
const double boltzman=1.380658000e-23; // Joule/Kelvin
const double elemcharge=1.602177330e-19; // Coulomb
const double lightspeed=299792458.0; // meter/second
const double dielectric0=8.854187817e-12; // Coulomb^2/Newton/meter^2
const double electron_mass=9.1093897e-31; // kilogram

}


> How come Superman could stop bullets with his chest,
> but always ducked when someone threw a gun at him?

Good question.


Siemel Naran

unread,
Apr 28, 2004, 12:48:59 PM4/28/04
to
"Julie" <ju...@nospam.com> wrote in message
news:408FD34B...@nospam.com...
> JKop wrote:

> > As for macro functions: Similarly, there is absolutley NO JUSTIFICATION
for
> > their use. Inline functions are superior in every way, BAR NONE!
>
> Do you consider:
>
> #if defined (CODE_1)
> // some code
> #else if defined (CODE_2)
> // other code
> #endif
>
> the use of macros?

Don't know about JKop, but this seems fine to me. How else to have code
compiled for Windows only, or Borland only, or debug mode only?


Siemel Naran

unread,
Apr 28, 2004, 12:49:00 PM4/28/04
to
"Julie" <ju...@nospam.com> wrote in message
news:408FD298...@nospam.com...
> JKop wrote:

> > As for macro functions: Similarly, there is absolutley NO JUSTIFICATION
for
> > their use. Inline functions are superior in every way, BAR NONE!
>
> Please describe how to implement the (standard library) offsetof macro in
terms
> of an inline function that is 'far superior' (or at least equally
inferior!).

Use the C++ pointer to member mechanism. The offsetof is only for C.


Siemel Naran

unread,
Apr 28, 2004, 12:49:02 PM4/28/04
to
"Michiel Salters" <Michiel...@logicacmg.com> wrote in message

> JKop <NU...@NULL.NULL> wrote in message news:<YPKjc.5878

> > As for macro functions: Similarly, there is absolutley NO JUSTIFICATION


for
> > their use. Inline functions are superior in every way, BAR NONE!
>
> inline int BYTES_NEEDED_FOR_INTS ( int no_ints )
> {
> return no_ints * sizeof(int);
> }
> typedef char[ BYTES_NEEDED_FOR_INTS( 5 ) ] int5;
>
> Does your compiler accept this?

BTW, is int5 above misplaced?

Anyway, that should be rewritten using structs and static const so that you
can use compile time constants. So basically I agree with JKop.

template <size_t N>
struct bytes_needed_for_ints
{
static const size_t result = N * sizeof(int);
};

typedef char int5[ BYTES_NEEDED_FOR_INTS<5>::result ];


Bill Seurer

unread,
Apr 28, 2004, 1:42:44 PM4/28/04
to
Siemel Naran wrote:

> Don't know about JKop, but this seems fine to me. How else to have code
> compiled for Windows only, or Borland only, or debug mode only?

if (platformSupportsXYZ()) {
. . .
} else {
. . .
}

Where platformSupportsXYZ() is a function that returns a const bool
value depending on whether the platform suports that feature (or
whatever). Just switch platforms when you, err switch platforms.
Optimization will eliminate the dead code.

Xenos

unread,
Apr 28, 2004, 2:32:22 PM4/28/04
to

"Bill Seurer" <seu...@us.ibm.com> wrote in message
news:c6oqek$1et8$1...@news.rchland.ibm.com...

How does this help you with definitions that are platform specific? Are you
going to define all the definitions from the headers of platforms' that
aren't being compiled for? And then creates stubs for all the functions?
And what about #include headers that aren't present because you are not
compiling for that system? What about all the compiler specific bugs,
quirks, etc.

Julie

unread,
Apr 28, 2004, 3:41:36 PM4/28/04
to

You can't say that offsetof is only for C, the macro exists in C++ (as well).

I've used offsetof in the past when packing/unpacking structure data into a
binary stream for serialization. Pointer-to-member has no meaning in this
context.

Jacek Dziedzic

unread,
Apr 28, 2004, 5:17:31 PM4/28/04
to
JKop wrote:

> [some anti-preprocessor hate rant]

I agree that things like
#define pi 3.14159265
are better expressed as
const double pi=3.13159265

but that's not all to macros. There are, IMHO, constructs that
don't translate well into inline functions. Consider a macro
like

#define for_all_masses_energies_and_momenta \
for(byte m=Lattice::MIN_MASS;m<=Lattice::MAX_MASS;m++) \
for(byte e=Lattice::MIN_ENERGY;e<=Lattice::MAX_ENERGY;e++) \
for(signed_bytevec p={Lattice::MIN_MOMENTUM_COMPONENT,
-1,-1};p[0]<=Lattice::MAX_MOMENTUM_COMPONENT;p[0]++) \
for(p[1]=Lattice::MIN_MOMENTUM_COMPONENT;
p[1]<=Lattice::MAX_MOMENTUM_COMPONENT;p[1]++) \
for(p[2]=Lattice::MIN_MOMENTUM_COMPONENT;
p[2]<=Lattice::MAX_MOMENTUM_COMPONENT;p[2]++) \

it allows me to write things like

for_all_masses_energies_and_momenta {
cout << m << " " << e << p[0] << p[1] << p[2] << endl
}

I think that as long as you're careful about these, remember
what they stand for and are aware of their limitations, they are
much more readable than

for(byte m=Lattice::MIN_MASS;m<=Lattice::MAX_MASS;m++)
for(byte e=Lattice::MIN_ENERGY;e<=Lattice::MAX_ENERGY;e++)
for(signed_bytevec p={Lattice::MIN_MOMENTUM_COMPONENT,
-1,-1};p[0]<=Lattice::MAX_MOMENTUM_COMPONENT;p[0]++)
for(p[1]=Lattice::MIN_MOMENTUM_COMPONENT;
p[1]<=Lattice::MAX_MOMENTUM_COMPONENT;p[1]++)
for(p[2]=Lattice::MIN_MOMENTUM_COMPONENT;
p[2]<=Lattice::MAX_MOMENTUM_COMPONENT;p[2]++)
{
// do whatever
}

even though they use the evil preprocessor.

Apart from that I know of no other mechanism that allows my
programs to compile differently when different options are
passed to the compiler. Thanks to things like
#ifdef PARRALEL
// use MPI
#else
// remain serial
#endif
I can make my program compile to two different things
depending on a compiler option. Can an inline function do
that?

just my $2e-2,
- J.

Jacek Dziedzic

unread,
Apr 28, 2004, 5:20:43 PM4/28/04
to
Bill Seurer wrote:

and how are you going to translate things like

#ifdef _WIN32
#include "time.h"
#else
#include "sys/time.h"
#endif

into the platformSupportsXYZ() lingo?

I'd stick to "macros are evil so use them only when you have to"
rule.

- J.

Alf P. Steinbach

unread,
Apr 28, 2004, 5:31:44 PM4/28/04
to
* Rolf Magnus <rama...@t-online.de> schriebt:

> > As for macro functions: Similarly, there is absolutley NO
> > JUSTIFICATION for their use. Inline functions are superior in every
> > way, BAR NONE!
>
> Right.

Well, Andrei Alexandrescu did once show what a bullet-proof "max" function
had to be like. Unfortunately I don't have a reference. I just remember
(vaguely) that it was hairy & sort of incomprehensible stuff.

We do have std::max and it works well in most situations, but it's not
perfect.

So I gather that there are situations, e.g. typewise, where a macro function
is the only practical way -- this aside from debugging and such, just
normal straightforward programming. But I think it would be a good idea in
project guidelines to restrict use of macro functions to some seniority
level and above. Huh, why didn't I think of that before?

--
A: Because it messes up the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

Julie

unread,
Apr 28, 2004, 5:55:51 PM4/28/04
to
"Alf P. Steinbach" wrote:
>
> * Rolf Magnus <rama...@t-online.de> schriebt:
> > > As for macro functions: Similarly, there is absolutley NO
> > > JUSTIFICATION for their use. Inline functions are superior in every
> > > way, BAR NONE!
> >
> > Right.
>
> Well, Andrei Alexandrescu did once show what a bullet-proof "max" function
> had to be like. Unfortunately I don't have a reference. I just remember
> (vaguely) that it was hairy & sort of incomprehensible stuff.
>
> We do have std::max and it works well in most situations, but it's not
> perfect.
>
> So I gather that there are situations, e.g. typewise, where a macro function
> is the only practical way -- this aside from debugging and such, just
> normal straightforward programming. But I think it would be a good idea in
> project guidelines to restrict use of macro functions to some seniority
> level and above. Huh, why didn't I think of that before?

Personally, I don't know what seniority has to do w/ anything relating to
anything at all. I'd be hard-pressed to find a term that is more abused,
subjective, and downright useless, but that is just my experience in being a
developer for 15+ years at numerous companies...

How about something a little more practical *and* beneficial to the staff
(especially non-'senior' staff) such as: reserved for those that have a
(fairly?) complete understanding of the preprocessor and have thoroughly
studied (and been tested on?) the project/team notes, comments, references, and
dissection of the preprocessor (or specifically macros).

Honestly (digressing from Alf's response), I feel that these types of threads
such as "NO JUSTIFICATION for [macros]" serves absolutely no one. How about a
complete and unbiased dissection of the preprocessor in all of its glory (or
lack thereof), compared and contrasted w/ potential substitute C++ (and C)
constructs and idioms so that people can actually *LEARN* something of value,
other than people's individual agendas or senseless blather. If there is such
a dissection of the preprocessor, I'd love to hear about it and read it, but to
date, I've never ran across anything other than topical/cursor examinations of
the preprocessor, and most conclude w/ the same "don't use it" result, rather
than leaving that determination up to the user.

Jack Klein

unread,
Apr 28, 2004, 11:58:50 PM4/28/04
to
On Wed, 28 Apr 2004 09:29:28 GMT, JKop <NU...@NULL.NULL> wrote in
comp.lang.c++:

> const unsigned short int AmountHumanAdultTeeth = 32;

[snip]

> Thus, concordantly and therefore, you most certainly _are_ taking up memory
> by using a macro instead of a const global variable.

You seem to be confused. The term "global" does not exist in C++.
Assuming you mean external linkage, you are wrong. The definition of
unsigned short int above has either internal or no linkage, depending
on whether its definition is at namespace or block scope.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html

Old Wolf

unread,
Apr 29, 2004, 12:11:25 AM4/29/04
to
Julie <ju...@nospam.com> wrote:

JKop wrote:
> > As for macro functions: Similarly, there is absolutley NO JUSTIFICATION for
> > their use. Inline functions are superior in every way, BAR NONE!
>
> Please describe how to implement the (standard library) offsetof
> macro in terms of an inline function that is 'far superior'
> (or at least equally inferior!).

This seems to work:

template<typename T, typename S>
size_t offset_of(T S::*p)
{
S *t = 0;
return (char *)&(t->*p) - (char *)t;
}

Example usage:

#include <iostream>
struct s { int a; char b; double c; };
int main(void)
{
std::cout << offset_of(&s::c) << std::endl;
}

Note: If you're going to allow 0->blah in a macro,
you have to allow my example too. Personally I think both are UB.

Siemel Naran

unread,
Apr 29, 2004, 12:24:39 AM4/29/04
to
"Bill Seurer" <seu...@us.ibm.com> wrote in message news:c6oqek$1et8
> Siemel Naran wrote:

> > Don't know about JKop, but this seems fine to me. How else to have code
> > compiled for Windows only, or Borland only, or debug mode only?
>
> if (platformSupportsXYZ()) {
> . . .
> } else {
> . . .
> }

The stuff in ... may be compilable only on one platform. Like in Linux
include ncurses.h and use the functions in there, but in Windows include
conio.h and use the functions there and the function names are totally
different.


Siemel Naran

unread,
Apr 29, 2004, 12:24:41 AM4/29/04
to
"Jacek Dziedzic" <jacek__...@janowo.net> wrote in message

> but that's not all to macros. There are, IMHO, constructs that
> don't translate well into inline functions. Consider a macro
> like
>
> #define for_all_masses_energies_and_momenta \
> for(byte m=Lattice::MIN_MASS;m<=Lattice::MAX_MASS;m++) \
> for(byte e=Lattice::MIN_ENERGY;e<=Lattice::MAX_ENERGY;e++) \
> for(signed_bytevec p={Lattice::MIN_MOMENTUM_COMPONENT,
> -1,-1};p[0]<=Lattice::MAX_MOMENTUM_COMPONENT;p[0]++) \
> for(p[1]=Lattice::MIN_MOMENTUM_COMPONENT;
> p[1]<=Lattice::MAX_MOMENTUM_COMPONENT;p[1]++) \
> for(p[2]=Lattice::MIN_MOMENTUM_COMPONENT;
> p[2]<=Lattice::MAX_MOMENTUM_COMPONENT;p[2]++) \
>
> it allows me to write things like
>
> for_all_masses_energies_and_momenta {
> cout << m << " " << e << p[0] << p[1] << p[2] << endl
> }

It is indeed true that macro functions let you write nice looking code. But
the reason to stay away from them is that they're hard to maintain, don't
offer type safety, and hard to debug, among other reasons.

Siemel Naran

unread,
Apr 29, 2004, 12:24:42 AM4/29/04
to
"Alf P. Steinbach" <al...@start.no> wrote in message

> * Rolf Magnus <rama...@t-online.de> schriebt:

> Well, Andrei Alexandrescu did once show what a bullet-proof "max" function


> had to be like. Unfortunately I don't have a reference. I just remember
> (vaguely) that it was hairy & sort of incomprehensible stuff.
>
> We do have std::max and it works well in most situations, but it's not
> perfect.

What's wrong with std::max? Can you dig up the reference?


> So I gather that there are situations, e.g. typewise, where a macro
function
> is the only practical way -- this aside from debugging and such, just
> normal straightforward programming. But I think it would be a good idea
in
> project guidelines to restrict use of macro functions to some seniority
> level and above. Huh, why didn't I think of that before?

I don't think macro functions and variables are ever a good idea, unless
you're maintaining legacy code.

Something about your seniority idea bothers me, something along the lines of
allowing those with power to abuse their power. But that's getting OT.


David Harmon

unread,
Apr 29, 2004, 2:15:04 AM4/29/04
to
On Wed, 28 Apr 2004 16:48:58 GMT in comp.lang.c++, "Siemel Naran" <Sieme...@REMOVE.att.net> wrote,

>Very good answer. In my experience it is very rare to use address of a
>constant, such as these:

Sure, such as those. But if your template function takes its argument by const reference, then you have to go out of
your way to pass literal rvalues.

Bill Seurer

unread,
Apr 29, 2004, 8:57:06 AM4/29/04
to
Siemel Naran wrote:

You put those into platform specific modules and only compile the ones
for your system. I work on a project (multiple host, multiple platform)
where it is done and it takes a while to get used to it but it can be
done. You might not be able to get rid of all macro stuff but you can
get rid of most of it.

By the way, something else I work on (Xerces/Xalan from Apache) went the
other way. Someone who looked at the code one time described it as
"macros with some C++ thrown in".

Bill Seurer

unread,
Apr 29, 2004, 8:59:17 AM4/29/04
to
Jacek Dziedzic wrote:

> and how are you going to translate things like
>
> #ifdef _WIN32
> #include "time.h"
> #else
> #include "sys/time.h"
> #endif
>
> into the platformSupportsXYZ() lingo?

You might not be able to. Or perhaps
#include "time.h"
will work for both if you use the right options on the compiler to point
it at the proper directories for includes.

> I'd stick to "macros are evil so use them only when you have to"
> rule.

I agree.

Siemel Naran

unread,
Apr 30, 2004, 1:28:32 AM4/30/04
to
"Bill Seurer" <seu...@us.ibm.com> wrote in message news:c6qu33$1d96

> You put those into platform specific modules and only compile the ones
> for your system. I work on a project (multiple host, multiple platform)
> where it is done and it takes a while to get used to it but it can be
> done. You might not be able to get rid of all macro stuff but you can
> get rid of most of it.

You could also create a directories like win and unix, and put the platform
specific files into their respective directories.


Alf P. Steinbach

unread,
Apr 30, 2004, 1:43:35 AM4/30/04
to
* "Siemel Naran" <Sieme...@REMOVE.att.net> schriebt:

> "Alf P. Steinbach" <al...@start.no> wrote in message
> > * Rolf Magnus <rama...@t-online.de> schriebt:
>
> > Well, Andrei Alexandrescu did once show what a bullet-proof "max" function
> > had to be like. Unfortunately I don't have a reference. I just remember
> > (vaguely) that it was hairy & sort of incomprehensible stuff.
> >
> > We do have std::max and it works well in most situations, but it's not
> > perfect.
>
> What's wrong with std::max? Can you dig up the reference?

Googled on "Andrei Alexandrescu max" and there it was second in the list,
<url: http://www.cuj.com/documents/s=7996/cujcexp1904alexandr/>.


> > So I gather that there are situations, e.g. typewise, where a macro
> function
> > is the only practical way -- this aside from debugging and such, just
> > normal straightforward programming. But I think it would be a good idea
> in
> > project guidelines to restrict use of macro functions to some seniority
> > level and above. Huh, why didn't I think of that before?
>
> I don't think macro functions and variables are ever a good idea, unless
> you're maintaining legacy code.

Not sure what you mean. A for-loop is one way to create a scope inside
a macro, while leaving semicolon usage in client code intact.


> Something about your seniority idea bothers me, something along the lines of
> allowing those with power to abuse their power. But that's getting OT.

Uhm, yes. ;-)

Siemel Naran

unread,
Apr 30, 2004, 4:26:33 PM4/30/04
to
"Alf P. Steinbach" <al...@start.no> wrote in message

> Googled on "Andrei Alexandrescu max" and there it was second in the list,
> <url: http://www.cuj.com/documents/s=7996/cujcexp1904alexandr/>.

<Quote>
As Scott notes, adding a second version:
template <class T>
T& min(T& lhs, T& rhs)
{
return lhs < rhs ? lhs : rhs;
}
still won't work satisfactorily because the compiler won't be able to figure
out mixed cases - one const and one non-const argument.
</Quote>

I don't understand this. Why would you call min with one argument const and
the other not. What should min return -- the T& or const T&?

<Quote>
Furthermore, templates don't play nicely with automatic conversion and
promotions, which means that the following code won't compile:

int a;
short int b;
...
int smallest = min(a, b); // error: can't figure out T
// in template instantiation
Needless to say, the macro-based min works nicely again with such
conversions
</Quote>

That's OK usually. Usually I like the type safety std::min.

Incidentally, Andrei lists a traits mechanism by which short + long ==>
long, etc. This is one place where typeof would be nice.


Alf P. Steinbach

unread,
Apr 30, 2004, 4:39:28 PM4/30/04
to
* "Siemel Naran" <Sieme...@REMOVE.att.net> schriebt:
> "Alf P. Steinbach" <al...@start.no> wrote in message
>
> > Googled on "Andrei Alexandrescu max" and there it was second in the list,
> > <url: http://www.cuj.com/documents/s=7996/cujcexp1904alexandr/>.
>
> <Quote>
> As Scott notes, adding a second version:
> template <class T>
> T& min(T& lhs, T& rhs)
> {
> return lhs < rhs ? lhs : rhs;
> }
> still won't work satisfactorily because the compiler won't be able to figure
> out mixed cases - one const and one non-const argument.
> </Quote>
>
> I don't understand this. Why would you call min with one argument const and
> the other not. What should min return -- the T& or const T&?

The latter. In this case you're not interested in using the result as a
non-const lvalue. Or if that is what is attempted then it is a logic error.

I'm not sure why the compiler shouldn't be able to figure out the overload,
though.

But then all that interests me is that there are complications, not the
complications themselves as such (my take is: keep things simple).

0 new messages