Macro Destroyer

R

Richard Herring

Chris Theis said:
[...]
5) #define public private

Note: A keyword being redefined - there's obviously some sort of intentional
hack going on here, so I'll leave it alone!

If you encounter such a hack there is certainly something very wrong
regarding some design issue ;-)

#define for if (0) {} else for

is not uncommon.
 
J

JKop

#define for if (0) {} else for

is not uncommon.


Why is this done?

Is it something to do with compilers that incorrectly advertise themselves
as C++ compilers, when they don't follow scoping rules correctly?

In the Visual Studio C++ settings, there's things like:

"Treat wchar_t as an inbuilt type: Yes"

"Follow correct scope rules with for: Yes"


Where's the dignity?


-JKop
 
C

Catalin Pitis

I can see this having the potential to cause linker errors. The types
will be marked as being in namespace Win, but in fact they are global.
This might cause problems with C++'s typesafe linking (e.g. name
mangling) that extern "C" doesn't fully negate, but you'll have to try
it to be sure.

Tom

I remember that I tried once to include windows.h in a namespace. It doesn't
work. And yet, the macros are not dependent on the namespaces. They will
still exist as globals.

Another issue is that windows.h is filled with #ifdef s which depend on
different symbols (like NT specific symbols or other platform version
specifics). How can these cases be handled?

One conclusion that I reached some time ago is: Let the windows.h like it
is. Don't touch it.

Catalin
 
J

JKop

I'm starting with the easiest one:

#define LRESULT long


When I'm parsing the file, it'll be very simple to spot these, just look out
for the names of the intrinsic types! (No, I'm not forgetting pointers!)

First thing though, I'm going to look-up the rules for "#define" statements,
eg. are you allowed put in white space/tabs etc...


-JKop
 
R

Richard Herring

[QUOTE="JKop said:
#define for if (0) {} else for

is not uncommon.

Why is this done?

Is it something to do with compilers that incorrectly advertise themselves
as C++ compilers, when they don't follow scoping rules correctly?[/QUOTE]

It's to do with compilers which follow an earlier version of the
standard, or predate it altogether.
In the Visual Studio C++ settings, there's things like:

"Treat wchar_t as an inbuilt type: Yes"

"Follow correct scope rules with for: Yes"

Where's the dignity?

It means you can keep old pre-standard code working. If you're trying to
include windows.h, that may be an important objective.
 
R

Ron Natalie

In the Visual Studio C++ settings, there's things like:

"Treat wchar_t as an inbuilt type: Yes"

"Follow correct scope rules with for: Yes"

Older versions of Visual C++ do not have this feature.
They have a single flag that says "disable microsnot extensions"
which if you turn on, you can't compile anything that includes
a Microsoft header.
 
C

Chris Theis

Richard Herring said:
Chris Theis said:
[...]
5) #define public private

Note: A keyword being redefined - there's obviously some sort of intentional
hack going on here, so I'll leave it alone!

If you encounter such a hack there is certainly something very wrong
regarding some design issue ;-)

#define for if (0) {} else for

is not uncommon.

Yes, you´re absolutely right on that and I´m also using it in a project
because I have to. But in principle it´s a hack for a shortcoming of the
VC++ 6.0 compiler (and probably others). In general it´s good practice not
to redefine keywords as it will certainly irritate other members of a
development team if some things don´t work as they are expected. Of course
you´ll find redefinitions of keywords like "new" if you implement memory
tracers etc. but this is a special case and the user of the code should be
aware of it.

Cheers
Chris
 
J

JKop

template<class A, class B, class ReturnType>
inline ReturnType const & GREATERfunction( A &a, B &b, ReturnType const
&return_value = ( (a) > (b) ? (a) : (b) ) )
{
return return_value;
}


Well first thing I've noticed:

If the calling function supplies the argument "return_value", then the
temporary object is local to the calling function, whilst (correct me if I'm
wrong) if my default argument were to work, then the object would be local
to the GREATERfunction, right?

Nice try (seriously) but unfortunatly no banana:

int f( int a, int b = a );

int main() {}

The above should illustrate the problem. In short default
arguments aren't allowed to be dependant on other arguments.


This truly is bullshit. I'm surprised I even had to come this far.

Why in the name of God would a compiler not be able to determine from the
following, the return type:

template<class ReturnType, class A, class B>
inline ReturnType const & MAX(A& a, B& b)
{
return ( (a) > (b) ? (a) : (b) );
}


It's painfully obvious in the above what the return type is! I think this is
something that should be submitted to the Standard commitee.


(BTW: I'm not looking for a way to simply turn MAX into a function, I'm
trying to find a universal way to turn any macro function into a proper
function.)


-JKop
 
I

Ioannis Vranos

JKop said:
This truly is bullshit. I'm surprised I even had to come this far.

Why in the name of God would a compiler not be able to determine from the
following, the return type:

template<class ReturnType, class A, class B>
inline ReturnType const & MAX(A& a, B& b)
{
return ( (a) > (b) ? (a) : (b) );
}




What's that? You try to return a const reference of a temporary.

Also a and b should be of the same type anyway (or the equivalent
conversions will take place anyway), so make the above:

template<class A>
inline A MAX(const A &a, const A &b)
{
return ( a > b ? a : b );
}




It's painfully obvious in the above what the return type is! I think this is
something that should be submitted to the Standard commitee.


(BTW: I'm not looking for a way to simply turn MAX into a function, I'm
trying to find a universal way to turn any macro function into a proper
function.)


You can't. Macros are a world of their own, the "macro substitution
paradigm". :)


Macros simply replace text with another equivalent text. You can replace
simple macro functions with templates automatically, but there are other
absurd uses that a program can't automatically figure out what is going on.

The compiler does not static check macros, the preprocessor processes
macros by performing the replacements, before the compiling phase.
 
J

JKop

template<class A>
inline A MAX(const A &a, const A &b)
{
return ( a > b ? a : b );
}


I'd make that return a reference.


Anyway:


int main()
{
Max(base_object, derived_object); //No problemo

Max(derived_object, base_object); //AAAAaahh!
}


The phrase "It could all be so simple..." comes to mind.

-JKop
 
I

Ioannis Vranos

JKop said:
I'd make that return a reference.


Anyway:


int main()
{
Max(base_object, derived_object); //No problemo

Max(derived_object, base_object); //AAAAaahh!
}


Actually both are errors. Consider this:


template<class A>
inline const A &MAX(const A &a, const A &b)
{
return a > b ? a : b ;
}


class base
{
};


class derived:public base
{
public:

// For automatic conversion of base objects
derived(const base &) {}
derived(){}
};


bool operator>(const derived &, const derived &) { return true; }

bool operator>(const base &, const base &) { return true; }


int main()
{
base base_object;

derived derived_object;

MAX<derived>(base_object, derived_object);
}




The clarification of the type is up to the programmer, as this only
makes sense.

The compiler can't read your mind which type you want.
 
R

Rob Williscroft

JKop wrote in in
comp.lang.c++:
template<class A, class B, class ReturnType>
inline ReturnType const & GREATERfunction( A &a, B &b, ReturnType
const &return_value = ( (a) > (b) ? (a) : (b) ) )
{
return return_value;
}


Well first thing I've noticed:

If the calling function supplies the argument "return_value", then the
temporary object is local to the calling function, whilst (correct me
if I'm wrong) if my default argument were to work, then the object
would be local to the GREATERfunction, right?

Yep and you then return a const reference to it which would refer
to something that will be destroyed when the function return's, but
that could be easily fixed by changing the return type.
This truly is bullshit. I'm surprised I even had to come this far.

Why bullshit, do you seriously expect a programming language to do
every thing you can possibly want to do, a C++ compiler is just
a computer programme not a sentient being.
Why in the name of God would a compiler not be able to determine from
the following, the return type:

template<class ReturnType, class A, class B>
inline ReturnType const & MAX(A& a, B& b)
{
return ( (a) > (b) ? (a) : (b) );
}

Determening the return type is not the problem, in the future (after
the next standard) it may be possible to write this:

template < typename A, typename B, >
auto max( A &a, B &b ) -> decltype( (a) > (b) ? (a) : (b) )
{
return ( (a) > (b) ? (a) : (b) );
}

Which does what you want, but notice the whole new syntax thats
been invented to handle this.
It's painfully obvious in the above what the return type is! I think
this is something that should be submitted to the Standard commitee.

You're a sentient being, not a dumb computer programme like a C++
compiler is. However:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1607.pdf
(BTW: I'm not looking for a way to simply turn MAX into a function,
I'm trying to find a universal way to turn any macro function into a
proper function.)

Not allways what you want:

#include <stdlib.h> // vc #defines _MAX_PATH

#define MAX( a, b ) ( (a) > (b) ? (a) : (b) )

template < int I > struct example
{
char buffer[ i ];
};

example< MAX( _MAX_PATH, 200 ) > my_example;

Won't work if you turn MAX into a function.

Rob.
 
J

Jerry Coffin

[ ... ]
Nice try (seriously) but unfortunatly no banana:

int f( int a, int b = a );

Assuming this was allowed, what would you expect in a case like:

int a = f(++x);

? Should the b=a be treated like a macro substitution, so x gets
incremented twice (and the values of a and b are different), or should
it be treated as an assignment to a and then from there to b? In the
latter case, you're basically forcing order of evaluation of the
function arguments, which C and C++ have specifically disavowed for
years. If you treat it like a macro substitution, that brings its own
set of ugliness -- and particularly, makes default argument values
radically different from other parameter passing.
 
R

Rob Williscroft

Jerry Coffin wrote in
in comp.lang.c++:
[ ... ]
Nice try (seriously) but unfortunatly no banana:

int f( int a, int b = a );

Assuming this was allowed, what would you expect in a case like:

I'm not sure I want it to be allowed, but ...
int a = f(++x);

? Should the b=a be treated like a macro substitution, so x gets
incremented twice (and the values of a and b are different),

That dosen't seem resonable, arguments in C++ are passed by
initialization rules, so I would expect:

a = x + 1, b = a, x = x + 1.

or

a = x + 1, x = x + 1, b = a.
or should
it be treated as an assignment to a and then from there to b? In the
latter case, you're basically forcing order of evaluation of the
function arguments, which C and C++ have specifically disavowed for
years.

Only when the default isn't given.
If you treat it like a macro substitution, that brings its own
set of ugliness -- and particularly, makes default argument values
radically different from other parameter passing.

Agreed.

Rob.
 
J

JKop

Jerry Coffin posted:
[ ... ]
Nice try (seriously) but unfortunatly no banana:

int f( int a, int b = a );

Assuming this was allowed, what would you expect in a case like:

int a = f(++x);

? Should the b=a be treated like a macro substitution, so x gets
incremented twice (and the values of a and b are different), or should
it be treated as an assignment to a and then from there to b?


I'd expect a const reference. No more, no less.

It's ludicrious to suggest a macro substitution!

In the
latter case, you're basically forcing order of evaluation of the
function arguments, which C and C++ have specifically disavowed for
years. If you treat it like a macro substitution, that brings its own
set of ugliness -- and particularly, makes default argument values
radically different from other parameter passing.


Hence I never would, have, nor will suggest such.


-JKop
 

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,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top