C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Preprocessor Push/Pop Idiom, How To?
Goto page 1, 2  Next
 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
new.netins.net
Guest





PostPosted: Fri Sep 29, 2006 10:09 pm    Post subject: Preprocessor Push/Pop Idiom, How To? Reply with quote



I wan't to save the current value of a manifest constant on a stack, and set

the value to another value. Later, I want to restore the previous value.
I'd like this ability to nest.
I.e. I want a preprocessor stack.
Imagine preprocessor directives #push and #pop, such that:

#define MY_VALUE 10 // MY_VALUE == 10
#push MY_VALUE 20 // now MY_VALUE == 20
#push MY_VALUE 30 // MY_VALUE == 30, ...
#pop MY_VALUE // restored, MY_VALUE
#pop MY_VALUE // MY_VALUE = 10
#pop MY_VALUE // undefined, could be not define, could be 10, dunno

How can I approximate this behavior?

terry



--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Ron Natalie
Guest





PostPosted: Sat Sep 30, 2006 12:02 am    Post subject: Re: Preprocessor Push/Pop Idiom, How To? Reply with quote



new.netins.net wrote:

Quote:
How can I approximate this behavior?

Use const variables and scopes:


const int MY_VALUE = 10;
{
const int MY_VALUE = 20;

{
const int MY_VALUE = 30;
}
// MY_VALUE = 20

}
// MY_VALUE = 10

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Terry G
Guest





PostPosted: Sat Sep 30, 2006 3:34 am    Post subject: Re: Preprocessor Push/Pop Idiom, How To? Reply with quote



"Ron Natalie" <ron (AT) spamcop (DOT) net> wrote in message
news:451d5f93$0$24194$9a6e19ea (AT) news (DOT) newshosting.com...
Quote:
new.netins.net wrote:
Use const variables and scopes:

Thank you for your help.
I need everything to be independent of scope.
I really want MY_VALUE to be a manifest constant and not a "const int".
The reason for this is that its used in another macro.
The idea is that MY_VALUE is a default that is applied to an entire
compilation unit (.h or .cpp file).
I probably over-simplified my code for the example.
Here's more over-simplified code.

#define SHORTHAND MyTemplate<MY_VALUE, long, 32>

If the user writes

#define MY_VALUE 10
SHORTHAND a;
#push MY_VALUE 20
SHORTHAND b;
#push MY_VALUE 30
SHORTHAND c;
#pop MY_VALUE
SHORTHAND d;
#pop MY_VALUE
SHORTHAND e;

The code emitted after the preprocessing phase should be:

MyTemplate<10, long, 32> a;
MyTemplate<20, long, 32> b;
MyTemplate<30, long, 32 > c;
MyTemplate<20, long, 32> d;
MyTemplate<10, long, 32> e;

If this helps, replace SHORTHAND with INT32, MyTemplate with Endian,
MY_VALUE with ENDIAN_DEFAULT, and (10, 20, 30) with (LITTLE_ENDIAN,
BIG_ENDIAN, and NATIVE_ENDIAN).

terry



--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Frederick Gotham
Guest





PostPosted: Sat Sep 30, 2006 6:47 am    Post subject: Re: Preprocessor Push/Pop Idiom, How To? Reply with quote

Ron Natalie posted:

Quote:
const int MY_VALUE = 10;


I suggest that ALL CAPS be used for macros and macros only.

--

Frederick Gotham

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Ron Natalie
Guest





PostPosted: Sat Sep 30, 2006 7:57 pm    Post subject: Re: Preprocessor Push/Pop Idiom, How To? Reply with quote

Frederick Gotham wrote:
Quote:
Ron Natalie posted:

const int MY_VALUE = 10;


I suggest that ALL CAPS be used for macros and macros only.

I suggest that you you are outdated.


I suggest that using all caps for manifest concepts is
as valid.

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
James Dennett
Guest





PostPosted: Sun Oct 01, 2006 1:44 am    Post subject: Re: Preprocessor Push/Pop Idiom, How To? Reply with quote

Ron Natalie wrote:
Quote:
Frederick Gotham wrote:
Ron Natalie posted:

const int MY_VALUE = 10;

I suggest that ALL CAPS be used for macros and macros only.

I suggest that you you are outdated.

I suggest that using all caps for manifest concepts is
as valid.

I suggest that the use of all caps for non-macro constants
is outdated, and that the reasons for segregating the
identifier namespace into APP_CAPS for macros (only) and
all other identifiers for non-macros is based on good
reasoning that has not diminished at all.

(It's unfortunate that other languages have picked up on
this and used ALL_CAPS for certain kinds of constants even
though they don't have a C-like preprocessor to work
around. APP_CAPS is not particularly readable. But that's
an aside.)

I see current best practice as reserving use of ALL_CAPS
for macros, and that has become more, not less, true over
the last decade.

There are still an unfortunate number of texts (usually
not the good ones, but sometimes even there) which don't
follow this sensible convention.

-- James

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Frederick Gotham
Guest





PostPosted: Sun Oct 01, 2006 1:45 am    Post subject: Re: Preprocessor Push/Pop Idiom, How To? Reply with quote

Ron Natalie posted:

Quote:
I suggest that ALL CAPS be used for macros and macros only.

I suggest that you are outdated.


I (or my methods, more like) will be outdated when macros have been done
away with, which, by the looks of things, won't happen any time soon.


Quote:
I suggest that using all caps for manifest concepts is
as valid.


Macros work slightly different from your usual functions, objects and
typedefs. For instance, take this macro function:

#define SQR(x) ((x)*(x))

This won't work in the way we would normally expect a function to work:

SQR(i++); /* Double-evaluation of the argument */

int (*p)(int) = SQR; /* Can't get a function pointer */

Also, consider the following macro typedef:

#define MY_TYPE int*

This macro won't work properly when used in such situations as:

void Func(const MY_TYPE arg) {}

This is a problem. A big problem. We need a reminder, something to pinch
us each and every time we make use of a macro -- Usher in ALL CAPS for
macros and for macros only.

If we were to start using ALL CAPS for things other than macros, then
we'd have a "Boy Who Cried Wolf" situation -- the pinch would get duller
and duller each time we deal with a non-macro... until eventually we
don't pay a blind bit of notice to ALL CAPS and we drop our level of
caution, leading to such mistakes as:

SQR(i++);

The use of ALL CAPS for anything other than macros should be shunned.

--

Frederick Gotham

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Alf P. Steinbach
Guest





PostPosted: Sun Oct 01, 2006 3:03 am    Post subject: Re: Preprocessor Push/Pop Idiom, How To? Reply with quote

* Ron Natalie:
Quote:
Frederick Gotham wrote:
Ron Natalie posted:

const int MY_VALUE = 10;

I suggest that ALL CAPS be used for macros and macros only.

I suggest that you you are outdated.

I suggest that using all caps for manifest concepts is
as valid.

You probably mean constants, not concepts.

The main rationale for the all caps convention for macros is that macros
don't respect scopes: we want to minimize name collisions.

Therefore, in original C, which lacked 'const', constants defined as
macros usually had all caps names.

That in-effect convention was picked up by programmers using other
languages, most notably Java, which lacks a preprocessor, and there used
in a way incompatible with the original goal of supporting use of the
preprocessor.

C++ is the direct descendant of the language where that convention
originated. In C++ the convention /in its original useful form/ is
still very much alive. Bringing the bastardized incompatible Java form
of that convention back into C++ would be, well, incongruous...

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

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Terry G
Guest





PostPosted: Sun Oct 01, 2006 2:59 pm    Post subject: Re: Preprocessor Push/Pop Idiom, How To? Reply with quote

"new.netins.net" <tjgolubi (AT) netins (DOT) net> wrote in message
news:efjh9f$2a$1 (AT) news (DOT) netins.net...
Quote:
I want to save the current value of a manifest constant on a stack, and set

the value to another value. Later, I want to restore the previous value.
I'd like this ability to nest.
I.e. I want a preprocessor stack.
Imagine preprocessor directives #push and #pop, such that:

#define MY_VALUE 10 // MY_VALUE == 10
#push MY_VALUE 20 // now MY_VALUE == 20
#push MY_VALUE 30 // MY_VALUE == 30, ...
#pop MY_VALUE // restored, MY_VALUE
#pop MY_VALUE // MY_VALUE = 10
#pop MY_VALUE // undefined, could be not define, could be 10, dunno

How can I approximate this behavior?

Here is a solution that DOES NOT WORK, but it represents what I wish
could be done.

#define MY_VALUE 10
#define MY_VALUE_temp MY_VALUE
#undef MY_VALUE
#define MY_VALUE 20
// Use MY_VALUE with value of 20.
#undef MY_VALUE
#define MY_VALUE MY_VALUE_temp
#undef MY_VALUE_temp
// MY_VALUE is restored to 10.

Again, I know this doesn't work, but I'm looking for a way to accomplish
the same thing. It seems impossible.

Would an extension to the C preprocessor to accomplish this be a good idea?
Surely someone has proposed this before.

#define MY_VALUE 10
#eval MY_VALUE_temp MY_VALUE // Expands right hand side before
assigning to
MY_VALUE_temp.
#undef MYVALUE
#define MY_VALUE 20
// Use MY_VALUE with value of 20.
#undef MY_VALUE
#eval MY_VALUE MY_VALUE_temp
#undef MY_VALUE_temp
// MY_VALUE is restored to 10.

#eval would be like := in gnu makefiles.
#swap X Y might be useful too. I don't think I'd like #push/#pop though.

Any thoughts?

terry


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Francis Glassborow
Guest





PostPosted: Sun Oct 01, 2006 7:57 pm    Post subject: Re: Preprocessor Push/Pop Idiom, How To? Reply with quote

In article <4o7h4lFdc1ofU1 (AT) individual (DOT) net>, Alf P. Steinbach
<alfps (AT) start (DOT) no> writes
Quote:
C++ is the direct descendant of the language where that convention
originated. In C++ the convention /in its original useful form/ is
still very much alive. Bringing the bastardized incompatible Java form
of that convention back into C++ would be, well, incongruous...

Yes, I completely agree, but I suspect there is another reason that
ALL_CAPS has crept into use for non-preprocessor names. I think that
many early adopters of C++ did not really understand why ALL_CAPS was
used in C for manifest constants. When they converted from using the
pre-processor to using const type definitions for manifest constants
they just transferred the original name. Of course there was another
pressure to do this, it meant that legacy C code could be 'improved' by
replacing
#define VAR 3
with
int const VAR(3);

and all the uses would remain working. I understand the reasoning here
but think that it is misplaced, just leave the original and the code
will work as intended.

What really irritates the h*** out of me is code such as:

enum colour {RED, BLUE, GREEN};

enumerators were never written as all caps in C (or not by programmers
who understood the divide between the pre-processor and other names)
but, of course, once you start using all caps for manifest constants you
obviously should do the same for enumeration constants.

Learn why things are done rather than simply see the superficial and you
will write code that is less vulnerable to the pre-processor.

--
Francis Glassborow ACCU
Author of 'You Can Do It!' and "You Can Program in C++"
see http://www.spellen.org/youcandoit
For project ideas and contributions:
http://www.spellen.org/youcandoit/projects

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Francis Glassborow
Guest





PostPosted: Sun Oct 01, 2006 7:57 pm    Post subject: Re: Preprocessor Push/Pop Idiom, How To? Reply with quote

In article <efn30e$5as$1 (AT) news (DOT) netins.net>, Terry G <tjgolubi (AT) netins (DOT) net>
writes
Quote:
Here is a solution that DOES NOT WORK, but it represents what I wish
could be done.

#define MY_VALUE 10
#define MY_VALUE_temp MY_VALUE
#undef MY_VALUE
#define MY_VALUE 20
// Use MY_VALUE with value of 20.
#undef MY_VALUE
#define MY_VALUE MY_VALUE_temp
#undef MY_VALUE_temp
// MY_VALUE is restored to 10.

Again, I know this doesn't work, but I'm looking for a way to accomplish
the same thing. It seems impossible.
My first reaction is 'excellent' the last thing I want in code is

constants that vary :)

The next reaction is that C++ programmers should be avoiding the use of
the pre-processor where possible because its use is full of unexpected
problems once you are writing more than trivial student code. The
biggest problem for C++ where real programs are often many tens or even
hundreds of thousands of lines long is the complete lack of any scope
for the pre-processor.

Now if you explain what the problem is that you think the above might
solve, then we might be able to suggest a solution. For now I find it
hard to understand why you want a variable constant :)

--
Francis Glassborow ACCU
Author of 'You Can Do It!' and "You Can Program in C++"
see http://www.spellen.org/youcandoit
For project ideas and contributions:
http://www.spellen.org/youcandoit/projects


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Gennaro Prota
Guest





PostPosted: Sun Oct 01, 2006 7:58 pm    Post subject: Re: Preprocessor Push/Pop Idiom, How To? Reply with quote

On 1 Oct 2006 05:59:17 -0400, "Terry G" <tjgolubi (AT) netins (DOT) net> wrote:

Quote:
[...]
Here is a solution that DOES NOT WORK, but it represents what I wish
could be done.

#define MY_VALUE 10
#define MY_VALUE_temp MY_VALUE
#undef MY_VALUE
#define MY_VALUE 20
// Use MY_VALUE with value of 20.
#undef MY_VALUE
#define MY_VALUE MY_VALUE_temp
#undef MY_VALUE_temp
// MY_VALUE is restored to 10.

Again, I know this doesn't work, but I'm looking for a way to accomplish
the same thing. It seems impossible.

I'm not sure I understand the details of what "the same thing" is
(which is crucial in this case) but... did you consider
Boost.Preprocessor's evaluated slots?

--
Gennaro Prota

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Jeffrey Schwab
Guest





PostPosted: Mon Oct 02, 2006 5:53 am    Post subject: Re: Preprocessor Push/Pop Idiom, How To? Reply with quote

Alf P. Steinbach wrote:
Quote:
* Ron Natalie:
Frederick Gotham wrote:
Ron Natalie posted:

const int MY_VALUE = 10;
I suggest that ALL CAPS be used for macros and macros only.

I suggest that you you are outdated.

I suggest that using all caps for manifest concepts is
as valid.

You probably mean constants, not concepts.

The main rationale for the all caps convention for macros is that macros
don't respect scopes: we want to minimize name collisions.

Therefore, in original C, which lacked 'const', constants defined as
macros usually had all caps names.

That in-effect convention was picked up by programmers using other
languages, most notably Java, which lacks a preprocessor, and there used
in a way incompatible with the original goal of supporting use of the
preprocessor.

C++ is the direct descendant of the language where that convention
originated. In C++ the convention /in its original useful form/ is
still very much alive. Bringing the bastardized incompatible Java form
of that convention back into C++ would be, well, incongruous...

"Bastardized" is a little harsh. Smile While I agree that ALL_CAPS should
only be used for pre-processor macros in C and C++, it is very useful in
Java for making constants visually obvious. When I see an identifier in
Java, I ordinarily don't know who has modified this particular member
variable, and I have to consider that it might have different values
(and mean different things) at various points in the code. On the other
hand, an IDENTIFIER is clearly a public static final constant, and a
reader can see immediately that the actual value doesn't matter as much
as the fact that it is unique. Different language often use the same
convention to mean different things, and that's OK.

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Bart.van.Ingen.Schenau@ic
Guest





PostPosted: Mon Oct 02, 2006 9:53 pm    Post subject: Re: Preprocessor Push/Pop Idiom, How To? Reply with quote

Terry G wrote:
Quote:
"Ron Natalie" <ron (AT) spamcop (DOT) net> wrote in message
news:451d5f93$0$24194$9a6e19ea (AT) news (DOT) newshosting.com...
new.netins.net wrote:
Use const variables and scopes:

Thank you for your help.
I need everything to be independent of scope.
I really want MY_VALUE to be a manifest constant and not a "const int".
The reason for this is that its used in another macro.
The idea is that MY_VALUE is a default that is applied to an entire
compilation unit (.h or .cpp file).
I probably over-simplified my code for the example.
Here's more over-simplified code.

#define SHORTHAND MyTemplate<MY_VALUE, long, 32

If the user writes

#define MY_VALUE 10
SHORTHAND a;
#push MY_VALUE 20
SHORTHAND b;
#push MY_VALUE 30
SHORTHAND c;
#pop MY_VALUE
SHORTHAND d;
#pop MY_VALUE
SHORTHAND e;

The code emitted after the preprocessing phase should be:

MyTemplate<10, long, 32> a;
MyTemplate<20, long, 32> b;
MyTemplate<30, long, 32 > c;
MyTemplate<20, long, 32> d;
MyTemplate<10, long, 32> e;

How about adding a parameter to your SHORTHAND macro:
#define SHORTHAND(value) MyTemplate<value, long, 32>

This can be used as:
SHORTHAND(10) a;
SHORTHAND(20) b;
SHORTHAND(30) c;
SHORTHAND(20) d;
SHORTHAND(10) e;

and will come out exactly as the expected result you give above.

Quote:

If this helps, replace SHORTHAND with INT32, MyTemplate with Endian,
MY_VALUE with ENDIAN_DEFAULT, and (10, 20, 30) with (LITTLE_ENDIAN,
BIG_ENDIAN, and NATIVE_ENDIAN).

terry

Bart v Ingen Schenau



--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Jason Hise
Guest





PostPosted: Mon Oct 02, 2006 10:11 pm    Post subject: Re: Preprocessor Push/Pop Idiom, How To? Reply with quote

If you are ok with something compiler specific:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html
/vcrefpop_macro.asp


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.