I was doing some Win32 programming today, having to include the file
"windows.h". Anyway, I'm thinking of writing a program that'll work like so:
macrodestroyer.exe windows.h
What this program will do is scour through the file, replacing all macros
with global const variables and inline functions. So for instance, if you
have:
#define MAX_LOADSTRING 100
It'll become:
unsigned const MAX_LOADSTRING = 100;
And if you have:
#define Minus5(t) (t-5)
Then'd be turned into
template <class T,class R>
inline T Minus5(R r)
{
return (t-5);
}
Or something along those lines.
Anyway...
The main benefits of this would be:
A) Follows scoping rules, and you could wrap "windows.h" in a namespace, eg:
namespace Win { #include "windows.h" }
B) You wouldn't have the problem of:
SomeMacro(++i);
in that it may increment it more than once.
Also, I would turn:
#define LRESULT long;
into:
typdef long LRESULT;
Anyway, before I get going on this little pet project, has this been done
before?
Any ideas, comments at all?
-JKop 41 2225
It is OK project, but it is highly chance that is not work OK. Reason for
this my be different meaning of:
#define MACROTYPE type*
and
typedef type MYTYPE
This two forms are different in term of:
MACROTYPE a, b;
is:
type *a, b; // b is not pointer to type
but in real typedef (MYTYPE)
MYTYPE a, b; // a and b are pointers.
I realy do not know is something like this is present in windows.h so than
your project have chance :)
hari4063 posted: It is OK project, but it is highly chance that is not work OK. Reason for this my be different meaning of:
#define MACROTYPE type*
and
typedef type MYTYPE
This two forms are different in term of:
MACROTYPE a, b;
is: type *a, b; // b is not pointer to type
but in real typedef (MYTYPE)
MYTYPE a, b; // a and b are pointers.
I realy do not know is something like this is present in windows.h so than your project have chance :)
That's a very good thing to point out, I hadn't thought of that.
I'll look into it...
-JKop
"JKop" <NU**@NULL.NULL> wrote in message
news:tn*******************@news.indigo.ie... I was doing some Win32 programming today, having to include the file "windows.h". Anyway, I'm thinking of writing a program that'll work like so:
macrodestroyer.exe windows.h
What this program will do is scour through the file, replacing all macros with global const variables and inline functions. So for instance, if you have:
[examples reordered for discussion]
#define MAX_LOADSTRING 100 It'll become: unsigned const MAX_LOADSTRING = 100;
Hum, why *unsigned* ? (the value could be -100)
I tend to prefer enum { MAX_LOADSTRING = 100 }; for such things anyway.
[ incorrect trailing ; removed from the next line ] #define LRESULT long into: typdef long LRESULT;
Note that the two previous cases will not always be easy to distinguish.
Consider:
#define THIS_STATUS_CODE SOME_PREVIOUS_ID
Should this become a typedef or a const?
You may need to parse #include-d files to find out...
The problem is aggravated by the fact that SOME_PREVIOUS_ID
may not even have been seen when the macro is defined.
How will you translate:
#define a b
// ... many lines or files later:
#define b int // or could be 0x00000000 instead of 'int'
Also, in <windows.h>, you will find a lot of macros such as:
#define GetWindowText GetWindowTextA
Which would best be translated into something like (e.g.):
inline BOOL GetWindowText(HANDLE h, CHAR* p)
{ return GetWindowTextA(h,p); }
These may additionally be conditionally compiled:
#ifndef UNICODE
#define GetWindowText GetWindowTextA
#else
#define GetWindowText GetWindowTextW
#endif
#define Minus5(t) (t-5)
Then'd be turned into
template <class T,class R> inline T Minus5(R r) { return (t-5); }
Beware that this may not always be equivalent.
In particular, it may generate additional member copies.
The main benefits of this would be:
A) Follows scoping rules, and you could wrap "windows.h" in a namespace, eg:
namespace Win { #include "windows.h" }
B) You wouldn't have the problem of:
SomeMacro(++i);
in that it may increment it more than once.
Yes, but then someone will accidentally compile the code
with the original version of <windows.h> and eventually
face strange and unexpected bugs.
Anyway, before I get going on this little pet project, has this been done before?
Any ideas, comments at all?
As you can tell, this is not a trivial task: you need
a preprocessor, a parser, and probably need to scan
all files together prior to processing.
I sympathize...
but I've given up long ago (locally) modifying files supplied
by a vendor. Better wrap and encapsulate them into
your own files/classes.
Regards,
Ivan
-- http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form
So, ... if you make this project, please pass mail to me (i will be glad to
see this, for free-or-not :)
My first task will be:
#pragma once
becomes:
#ifndef INCLUDE_BLAH_HPP
#define INCLUDE_BLAH_HPP
//contents of file
#endif
"Ivan Vecerina" <NO**********************************@vecerina.com > schrieb
im Newsbeitrag news:ck**********@newshispeed.ch...
[SNIP] #define MAX_LOADSTRING 100 It'll become: unsigned const MAX_LOADSTRING = 100; Hum, why *unsigned* ? (the value could be -100) I tend to prefer enum { MAX_LOADSTRING = 100 }; for such things anyway.
You could also run into trouble with enum. IMHO it would be crucial to check
thoroughly the value of the assignment and produce code accordingly.
[SNIP]
Cheers
Chris
"JKop" <NU**@NULL.NULL> schrieb im Newsbeitrag
news:tn*******************@news.indigo.ie... I was doing some Win32 programming today, having to include the file "windows.h". Anyway, I'm thinking of writing a program that'll work like
so: macrodestroyer.exe windows.h
What this program will do is scour through the file, replacing all macros with global const variables and inline functions. So for instance, if you have:
#define MAX_LOADSTRING 100
It'll become:
unsigned const MAX_LOADSTRING = 100;
And if you have:
#define Minus5(t) (t-5)
Then'd be turned into
template <class T,class R> inline T Minus5(R r) { return (t-5); }
Or something along those lines.
Anyway...
The main benefits of this would be:
A) Follows scoping rules, and you could wrap "windows.h" in a namespace,
eg: namespace Win { #include "windows.h" }
B) You wouldn't have the problem of:
SomeMacro(++i);
in that it may increment it more than once. Also, I would turn:
#define LRESULT long;
into:
typdef long LRESULT;
Anyway, before I get going on this little pet project, has this been done before?
Any ideas, comments at all?
You know the road to hell is paved with good intentions ;-) Some subtle
issues were already pointed out in other postings and in general the problem
is that you would have to perform a very careful & thorough parsing
(sometimes of the whole project!). Even with that you have a good chance to
screw up in many places because the intention of the #defines are different
and hard to interpret automatically. This will become even more difficult
when they are somehow interlinked.
Generally, fumbling with compiler manufacturer's headers are bound to give
you or somebody else trouble some day.
The idea of replacing the #pragma statement with ordinary include guards is
a good one and should not attract trouble but I'd stay away from the rest.
IMHO you can invest your time in a better way.
Regards
Chris
On Thu, 14 Oct 2004 11:26:17 GMT, JKop <NU**@NULL.NULL> wrote: I was doing some Win32 programming today, having to include the file "windows.h". Anyway, I'm thinking of writing a program that'll work like so:
macrodestroyer.exe windows.h
What this program will do is scour through the file, replacing all macros with global const variables and inline functions. So for instance, if you have:
#define MAX_LOADSTRING 100
It'll become:
unsigned const MAX_LOADSTRING = 100;
You should keep the type the same:
int const MAX_LOADSTRING = 100;
And if you have:
#define Minus5(t) (t-5)
Then'd be turned into
template <class T,class R> inline T Minus5(R r) { return (t-5); }
Or something along those lines.
That won't work:
Minus5(10); //error, what about the T parameter?
You need "typeof" or similar. e.g.
template <class T>
typeof(t-5) Minus5(T t)
{
return t-5;
}
Anyway...
The main benefits of this would be:
A) Follows scoping rules, and you could wrap "windows.h" in a namespace, eg:
namespace Win { #include "windows.h" }
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 That won't work:
Minus5(10); //error, what about the T parameter? You need "typeof" or similar. e.g. template <class T> typeof(t-5) Minus5(T t) { return t-5; }
Can the compiler not determine the return type from the return statement?
Off to do some experimentation. . .
-JKop
I'm going to start off with a broad checklist on this.
Obviously first of all, I'll deal with #define statements. Here's the kinds:
1) #define DAYS_IN_A_YEAR 365
Note: Will become a global const variable of the type of 365.
2) #define LRESULT long
Note: Will become a typedef
3) #define Minus5(a) (a - 5)
Note: Will become an inline function
4) #define WIN32_LEAN_AND_MEAN
Note: I'll leave these alone.
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!
After that:
1) #pragma once
Note: Will become inclusion guards.
Any other ideas?
Firstly I'm going to decide how I'll turn:
#define DAYS_IN_A_YEAR 365
into a global const variable. I'll have to devise a way of choosing the
right type...
-JKop
JKop wrote: I was doing some Win32 programming today, having to include the file "windows.h". Anyway, I'm thinking of writing a program that'll work like so:
macrodestroyer.exe windows.h
What this program will do is scour through the file, replacing all macros with global const variables and inline functions. So for instance, if you have:
#define MAX_LOADSTRING 100
It'll become:
unsigned const MAX_LOADSTRING = 100;
And if you have:
#define Minus5(t) (t-5)
Then'd be turned into
template <class T,class R> inline T Minus5(R r) { return (t-5); }
Or something along those lines.
Anyway...
The main benefits of this would be:
A) Follows scoping rules, and you could wrap "windows.h" in a namespace, eg:
namespace Win { #include "windows.h" }
B) You wouldn't have the problem of:
SomeMacro(++i);
in that it may increment it more than once. Also, I would turn:
#define LRESULT long;
into:
typdef long LRESULT;
Anyway, before I get going on this little pet project, has this been done before?
Any ideas, comments at all?
Well, why waste time with this old code?
In any case, in general if you want to create a program which converts
macro definitions to inline function definitions, etc I think you will
need to read some book about parsing.
If you are only interested about doing this for Win32 facilities, you
have better start reading about .NET and forget that old stuff. :-)
--
Ioannis Vranos http://www23.brinkster.com/noicys
On Thu, 14 Oct 2004 11:26:17 +0000, JKop wrote: I was doing some Win32 programming today, having to include the file "windows.h". Anyway, I'm thinking of writing a program that'll work like so:
macrodestroyer.exe windows.h
What this program will do is scour through the file, replacing all macros with global const variables and inline functions. So for instance, if you have:
<snip>
It's *really* important to keep in mind that #define's don't cause
anything to happen in the "real" file until invoked. They just define text
replacements for when a macro is eventually used. Here are some fun
cases (off the top of my head - not tested to be compilable):
Case 1
// order isn't important.
#define Y X+100
#define X 5
Case 2
// Usage of numeric #defines in other preprocessor contexts
#define VERSION 1
#ifdef VERSION
....
#endif
Case 2.1
#define VERSION 5
#if VERSION > 4
....
#endif
Case 3
// Definitions are transient and may be undone at any time.
#define X 10
// later, perhaps in a different file
#undef X
#define X 20
Case 4
// Anything with token pasting or stringizing...
#define AGE 29
#define SayAGE(a) puts("My age is " #a)
You can combine the above to your heart's discontent.
I would also be careful about wanting to remove side effects. Unless
you're using it for new code, there may be dependencies on those side
effects in existing code, sad as that may be.
Good luck!
- Jay
JKop wrote: I was doing some Win32 programming today, having to include the file "windows.h". Anyway, I'm thinking of writing a program that'll work like so:
macrodestroyer.exe windows.h
What this program will do is scour through the file, replacing all macros with global const variables and inline functions. So for instance, if you have:
This may be very disturbing for you to learn, but you and I think alike.
Just this morning I was thinking about something I was calling anti-macros.
(Kind of like anti-matter, but they won't power a starship.) The idea is
to replace all your macros with the CPP rendering, but store some kind of
tag that will reverse the process. Something like this would go around the
expansion. (There are obvious problems here. It's just a first stab.)
#pragma macro_begin NAME_OF_MACRO
The expanded form of the macro goes here.
#pragma macro_end NAME_OF_MACRO
The motivation for doing things that way would be to revert to the macro
form of the code when desired. I even went so far as to muse about
enhancing the CPP rather than abolishing it ... but that frightened me.
I have some other ideas, but I will probably put them in the KDevelope whish
list before I post them here.
--
"If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true." - Bertrand
Russell
JKop wrote: That won't work:
Minus5(10); //error, what about the T parameter? You need "typeof" or similar. e.g. template <class T> typeof(t-5) Minus5(T t) { return t-5; }
Can the compiler not determine the return type from the return statement?
I only wish. The one exception, which I have not explored are the
conversion operator member functions.
What am I missing here?
template <typename T>{ T Minus5(const T& t) { return t - 5;} }
NOTE: The use of 'class' for template parameters rather than 'typename' was
extremely confusing to me when first learning C++. I still find it less
intuitive than using 'typename'.
NOTE: For formal parameters, I always use 'const type& var' rather than
simply 'type var'. I don't recall the exact reasoning, but I was once given
a convincing argument to favor this approach. It has something to do with
passing literals such as '5'.
NOTE: I will do:
template <typename T>{ T f(T t) { return op(t); } } // on one line;
but not
for(int i; i < stop; i++) doit(); // no braces
That last statement would, in my code, be
for(int i; i < stop; i++) { doit(); }
It's just too easy to neglect to notice that doit2() in
for(int i; i < stop; i++)
doit();
doit2();
is not part of the for loop.
The reason I will put the above example on one line is because it allows me
to compact my code which often results in easier comparison of closely
related statements. I wouldn't, however do this:
template <typename T>{ T f(T t) { op2(t); return op(t); } } // BAD;
That starts looking like perl.
--
"If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true." - Bertrand
Russell
Chris Theis wrote: Generally, fumbling with compiler manufacturer's headers are bound to give you or somebody else trouble some day.
I agree that windoze.h is not something to try second guessing, but I
believe the general idea of pre-edit macro replacement has (great) merit.
--
"If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true." - Bertrand
Russell
"Steven T. Hatton" <su******@setidava.kushan.aa> wrote in message
news:Ot********************@speakeasy.net... Chris Theis wrote:
Generally, fumbling with compiler manufacturer's headers are bound to
give you or somebody else trouble some day.
I agree that windoze.h is not something to try second guessing, but I believe the general idea of pre-edit macro replacement has (great) merit.
I absolutely agree with you regarding the merit but I wanted to stress that
this is all but trivial and might become a monstrous task ;-)
Cheers
Chris
JKop wrote:
[snip] Any other ideas?
Just a few weeks back I did this:
#define LoadDLLFunction(name) \
(*(FARPROC*)&name = GetProcAddress( m_hDLL,#name)); \
if( name == NULL ) { \
AfxMessageBox( "DLL does not export:\n" #name ); \
}
LoadDLLFunction( func1 );
LoadDLLFunction( func2 );
It is used to lookup a function 'func1' in a DLL and store a pointer
to it in a function pointer variable with the same name as the function.
--
Karl Heinz Buchegger kb******@gascad.at
"JKop" <NU**@NULL.NULL> wrote in message
news:SX*******************@news.indigo.ie... I'm going to start off with a broad checklist on this.
Just some comments & remarks to make you aware of common pitfalls.
Obviously first of all, I'll deal with #define statements. Here's the
kinds:
1) #define DAYS_IN_A_YEAR 365
Note: Will become a global const variable of the type of 365.
2) #define LRESULT long
Note: Will become a typedef
It will be crucial how to differentiate between case 1 and 2. The
straightforward strategy might be to check the second argument of #define
and if it´s a number then you´ll have a constant. Otherwise a typedef is
what you´re looking for. But wait for a moment because the world is a little
more complicated. What about the following nested (and probably spread over
different files) declaration:
#define X_VAL 1
#define AXIS_X X_VAL
What will be the result of the second #define transformation? You can now
say - "piece of cake", I´ll only create typedefs if the second argument is a
token specifying a data-type like int, long, etc. Unfortunately there is
more trouble in store & especially using the MS windows headers you´ll have
to face it. Think of the following:
#define BYTE char
#define PCHAR BYTE*
or
#define BYTE char
#define MYCHAR BYTE
Furthermore keep in mind that the respective definitions might be spread
over different files!
3) #define Minus5(a) (a - 5)
Note: Will become an inline function
4) #define WIN32_LEAN_AND_MEAN
Note: I'll leave these alone.
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 ;-)
After that:
1) #pragma once
Note: Will become inclusion guards.
That´s a good idea & easy to solve. Any other ideas?
Firstly I'm going to decide how I'll turn:
#define DAYS_IN_A_YEAR 365
into a global const variable. I'll have to devise a way of choosing the right type...
If you´re really going for it then I wish you good luck and would recommend
to read up on parsing.
Cheers
Chris
Chris Theis wrote: "Steven T. Hatton" <su******@setidava.kushan.aa> wrote in message news:Ot********************@speakeasy.net... I agree that windoze.h is not something to try second guessing, but I believe the general idea of pre-edit macro replacement has (great) merit.
I absolutely agree with you regarding the merit but I wanted to stress that this is all but trivial and might become a monstrous task ;-)
It depends on what you want to accomplish. If your goal is to be 100%
comprehensive, you will end up with a rather large file in your edit buffer
if you have something such as #include <iostream> and a few of your own
headers as well.
I'm thinking along the lines of cookie-cutter code. Suppose you want to
create a unit test framework using a standard format for your test
functions. I've seen this done using macros. It's how the Boost unit test
stuff works. Basically you pass as macro arguments things such as the
names of the functions you want to invoke. These are expanded to use both
the function and a string representation of the function for output
purposes, etc. I'd be happy to have a tool along the lines of
tempotemplates (which will work), rather than CPP macros to do all of this.
But people do use macros, and they have the advantage (and shortcoming) that
they can be changed at one point in the code resulting in global changes.
And they are part of the C++ Standard, so they port.
--
"If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true." - Bertrand
Russell
In message <ck**********@sunnews.cern.ch>, Chris Theis
<Ch*********@nospam.cern.ch> writes "JKop" <NU**@NULL.NULL> wrote in message news:SX*******************@news.indigo.ie...
[...] 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.
--
Richard Herring #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
"Tom Widmer" <to********@hotmail.com> wrote in message
news:qa********************************@4ax.com... namespace Win { #include "windows.h" }
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 One conclusion that I reached some time ago is: Let the windows.h like it is. Don't touch it.
No way in hell am I giving up that easy :-D !
-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
In message <hY*******************@news.indigo.ie>, JKop <NU**@NULL.NULL>
writes #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?
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.
--
Richard Herring
"Richard Herring" <ju**@[127.0.0.1]> wrote in message
news:xX**************@baesystems.com... In message <ck**********@sunnews.cern.ch>, Chris Theis <Ch*********@nospam.cern.ch> writes "JKop" <NU**@NULL.NULL> wrote in message news:SX*******************@news.indigo.ie...
[...] 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 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.
Can anyone think of anything other than #define directives that I could
replace in source files?
One thing I can think of right now is turning:
typedef struct _RECTL
{
LONG left;
LONG top;
LONG right;
LONG bottom;
} RECTL, *PRECTL, *LPRECTL;
into:
struct RECTL
{
LONG left;
LONG top;
LONG right;
LONG bottom;
};
typedef RECTL* PRECTL;
typedef RECTL* LPRECTL;
Although that would be exiting from the realms of "changing how it works"
into the realms of "changing how it looks", ie. the effect would be purely
cosmetic and wouldn't effect the way in which you or the compiler works with
the file...
-JKop
JKop wrote: Can anyone think of anything other than #define directives that I could replace in source files?
One thing I can think of right now is turning:
typedef struct _RECTL { LONG left; LONG top; LONG right; LONG bottom; } RECTL, *PRECTL, *LPRECTL;
into:
struct RECTL { LONG left; LONG top; LONG right; LONG bottom; };
typedef RECTL* PRECTL; typedef RECTL* LPRECTL;
The above is not the same as the original. Also no one would use this tool.
--
Ioannis Vranos http://www23.brinkster.com/noicys
Ioannis Vranos posted: JKop wrote: Can anyone think of anything other than #define directives that I could replace in source files?
One thing I can think of right now is turning:
typedef struct _RECTL { LONG left; LONG top; LONG right; LONG bottom; } RECTL, *PRECTL, *LPRECTL;
into:
struct RECTL { LONG left; LONG top; LONG right; LONG bottom; };
typedef RECTL* PRECTL; typedef RECTL* LPRECTL; The above is not the same as the original. Also no one would use this tool.
*I* would!
-JKop
I've had my thinking cap on thinking of ways to tackle:
#define GREATERmacro(a,b) ( (a) > (b) ? (a) : (b) )
I thought a lightbulb appeared above my head when I thought of:
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;
}
But... for some reason, both my compilers are blatantly ignoring the default
argument I provide, ie. "( (a) > (b) ? (a) : (b) )".
The following won't compile:
int main()
{
int a = 5;
int b = 45;
GREATERfunction( a, b );
//In the above, it's telling me that it can't deduce the type
ReturnType
//While the following *does* work:
GREATERfunction( a, b, ( (a) > (b) ? (a) : (b) ) );
//ie. in the above, I'm explicitly providing the argument's value.
}
So my question is, why the hell is it paying no heed whatsoever to the
default argument value I'm giving it?!:
ReturnType const &return_value = ( (a) > (b) ? (a) : (b) )
-JKop
JKop wrote in news:K_*******************@news.indigo.ie 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; }
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.
However if you get a better compiler say gcc 3.4: http://www.thisiscool.com/gcc_mingw.htm
Then you would have got a simmilar error message with your
template function.
Regarding the MIN/MAX problem you might find this interesting: http://www.cuj.com/documents/s=7996/...r/alexandr.htm
Rob.
-- http://www.victim-prime.dsl.pipex.com/
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
JKop wrote: 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.
--
Ioannis Vranos http://www23.brinkster.com/noicys
Ioannis Vranos wrote: 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.
Consider the above phrase a mistake.
--
Ioannis Vranos http://www23.brinkster.com/noicys 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
JKop wrote: 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! }
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.
--
Ioannis Vranos http://www23.brinkster.com/noicys
JKop wrote in news:dB*******************@news.indigo.ie 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. 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 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/wg...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.
-- http://www.victim-prime.dsl.pipex.com/
Rob Williscroft <rt*@freenet.co.uk> wrote in message news:<Xn**********************************@130.133 .1.4>...
[ ... ] 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.
--
Later,
Jerry.
The universe is a figment of its own imagination.
Jerry Coffin wrote in
news:b2*************************@posting.google.co m in comp.lang.c++: Rob Williscroft <rt*@freenet.co.uk> wrote in message news:<Xn**********************************@130.133 .1.4>...
[ ... ]
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.
-- http://www.victim-prime.dsl.pipex.com/
Jerry Coffin posted: Rob Williscroft <rt*@freenet.co.uk> wrote in message news:<Xn**********************************@130.133 .1.4>...
[ ... ]
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 This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: Andrew Dalke |
last post by:
Here's a proposed Q&A for the FAQ based on a couple recent
threads. Appropriate comments appreciated
X.Y: Why doesn't Python have macros like in Lisp or Scheme?
Before answering that, a...
|
by: mike420 |
last post by:
I think everyone who used Python will agree that its syntax is
the best thing going for it. It is very readable and easy
for everyone to learn. But, Python does not a have very good
macro...
|
by: Pete |
last post by:
In Access 95/97 I used to be able to create pull down menus (File,Edit
...) from a macro. It seems there used to be some wizard for that.
However in Access 2000 it seems you have to build your...
|
by: Newbie_sw2003 |
last post by:
Where should I use them?
I am giving you my understandings. Please correct me if I am wrong:
MACRO:
e.g.:#define ref-name 99
The code is substituted by the MACRO ref-name. So no overhead....
|
by: Alexander Ulyanov |
last post by:
Hi all.
Is it possible to pass the whole blocks of code (possibly including
" and ,) as macro parameters?
I want to do something like:
MACRO(FOO, "Foo",
"return "Foobar";",
"foo();...
|
by: lasek |
last post by:
Hi...in some posts i've read...something about using macro rather then
function...but difference ??.
Best regards....
|
by: Takeadoe |
last post by:
Dear NG,
Can someone assist me with writing the little code that is needed to
run an update table query each time the database is opened? From what
I've been able to glean from this group, the...
|
by: Bill |
last post by:
This database has no forms. I am viewing an Access table in datasheet
view. I'd like to execute a macro to execute a function (using
"runcode"). In the function, I'll reading data from the record...
|
by: =?Utf-8?B?TGV0emRvXzF0?= |
last post by:
I'd like to create a Macro that will sort some raw data, apprx 20k lines,
remove some lines based upon a condition in a certain column. Then copy this
data into a new spreadsheet and sort the ...
|
by: CloudSolutions |
last post by:
Introduction:
For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
|
by: Faith0G |
last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
|
by: isladogs |
last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM).
In this session, we are pleased to welcome former...
|
by: taylorcarr |
last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
|
by: ryjfgjl |
last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
|
by: ryjfgjl |
last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
|
by: emmanuelkatto |
last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud.
Please let me know.
Thanks!
Emmanuel
|
by: BarryA |
last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
|
by: Sonnysonu |
last post by:
This is the data of csv file
1 2 3
1 2 3
1 2 3
1 2 3
2 3
2 3
3
the lengths should be different i have to store the data by column-wise with in the specific length.
suppose the i have to...
| |