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

Clarification on 'defined' operator

0 views
Skip to first unread message

Paul Mensonides

unread,
Jul 1, 2002, 12:55:45 PM7/1/02
to
Is the following legal? I.e. does it do what it implies?

#define X defined(Y)
#define Y

#if X
// ...
#else
// ...
#endif

16.1/4 says:

"If the token 'defined' is generated as a result of this replacement process or
use of the 'defined' unary operator does not match one of the two specified
forms prior to macro replacement, the behavior is undefined."

I'm curious what 'generated' means in this context. In the case above, the
token 'defined' is not generated so much as the expansion includes it. I would
understand if the 'defined' was generated as a result of concatenation or
something.

Here are the results on some compilers...

Comeau C++: works
Gcc 3.1: works
VC6: fails *
CWPro7.2: works
CWPro8: works
VC7: fails *
VC7.1: fails *
Mingw2.95: works
Intel5: works
GCC 3.0.4: works
Intel6: works

It only fails on VC, which leads me to believe that VC is wrong. Any
clarification would be helpful. By the way, I really want this to work. :)

Paul Mensonides

---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std...@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]

mackrune

unread,
Jul 3, 2002, 8:05:51 PM7/3/02
to
Paul Mensonides wrote:
|| Is the following legal? I.e. does it do what it implies?
||
|| #define X defined(Y)
|| #define Y
||
|| #if X
|| // ...
|| #else
|| // ...
|| #endif


#if defined(Y)
#define X 1
#else
#define X 0
#endif

mackrune

Paul Mensonides

unread,
Jul 3, 2002, 10:06:08 PM7/3/02
to
"mackrune" <rune420_r...@start.no> wrote in message
news:ag02a5$bgg$1...@troll.powertech.no...

> Paul Mensonides wrote:
> || Is the following legal? I.e. does it do what it implies?
> ||
> || #define X defined(Y)
> || #define Y
> ||
> || #if X
> || // ...
> || #else
> || // ...
> || #endif
>
>
> #if defined(Y)
> #define X 1
> #else
> #define X 0
> #endif
>
> mackrune

I'm working on the preprocessor library of Boost--right now on some mechanism
that use files as macros and macros as parameters--such as iteration and
calculation. For instance:

#define BOOST_PP_VALUE 1 + 2 + 3 + 4
#include BOOST_PP_ASSIGN_SLOT(1)

#undef BOOST_PP_VALUE // this is redundant

BOOST_PP_SLOT(1) // evaluates to '10'

So unfortunately, I can't hard-code the mechanism to work with *specific* names
like the one above. It has to be passed into mechanism by the user. The
ability to use 'defined' in an inlined context would avoid cluttering with
macros:

#define BOOST_PP_VALUE defined(X)
#include BOOST_PP_ASSIGN_SLOT(1)

BOOST_PP_SLOT(1) // evaluates to either '1' or '0'

This only works on compilers that support this kind of 'defined' indirection, so
I am wondering if it is undefined or not. By the way, VC6/7 seems to be the
only one that was tested that it failed on.

Paul Mensonides

James Dennett

unread,
Jul 6, 2002, 2:23:25 AM7/6/02
to

My reading of the Standard is that your code is not guaranteed
to work; replacement of "defined <identifier>" in conditional
inclusion directives is only guaranteed to occur once, before
macro expansion takes place. My not-fully-implement preprocessor
agrees with me, but then that doesn't say much -- if I'm wrong
now, I'll have been wrong when I wrote that code.

The Standard does seem to leave this undefined, so as a
reasonable extension it would make sense to be more aggressive
in replacing "defined(identifier)" or "defined identifier",
but my goal in writing a preprocessor is to highlight non-portable
code.

-- James.

Gennaro Prota

unread,
Jul 8, 2002, 12:06:47 PM7/8/02
to
On Sat, 6 Jul 2002 06:23:25 GMT, James Dennett <jden...@acm.org>
wrote:

>My reading of the Standard is that your code is not guaranteed
>to work

> ...


>The Standard does seem to leave this undefined

Yes. And just to resign ourselves, here's the (recent) response of the
C committee about such issues:

http://wwwold.dkuug.dk/JTC1/SC22/WG14/www/docs/dr_258.htm

The examples are slightly different, but the tone of the answer
doesn't leave much room to doubts: undefined behavior regardless of
whether the token "defined" was actually formed during macro
replacement (e.g. by means of the ## operator) or was already there.


P.S.: Paul, can you explain exactly what do BOOST_PP_VALUE and
BOOST_PP_SLOT do and what problem do they solve (not the intuitive
meaning, which can be easily inferred from what you wrote)?


Genny.

Paul Mensonides

unread,
Jul 8, 2002, 7:43:39 PM7/8/02
to
> P.S.: Paul, can you explain exactly what do BOOST_PP_VALUE and
> BOOST_PP_SLOT do and what problem do they solve (not the intuitive
> meaning, which can be easily inferred from what you wrote)?
>
>
> Genny.

Thanks Genny, I guess that clears it up the 'defined' issue for me. :(

Well, first, the slot mechanism is not part of any official release of Boost
yet, but I will explain anyway...

The mechanism is used with preprocessor metaprogramming, which is a complement
to template metaprogramming (i.e. it fills in some of the gaps).

What the slot mechanism does, is *evaluate* the expression and assign it to a
'slot'.

E.g.

#define X() 4
#define BOOST_PP_VALUE 1 + 2 + 3 + X()
#include BOOST_PP_ASSIGN_SLOT(1)
// ^ **include**

BOOST_PP_SLOT(1)

The macro BOOST_PP_VALUE is a user-defined macro that is used as a named
argument to the filename returned from BOOST_PP_ASSIGN_SLOT. The included file
evaluates the expression and assigns a raw value to a 'slot' contained in the
library. This value is accessible via BOOST_PP_SLOT. In the case above, slot
#1 is assigned, so BOOST_PP_SLOT(1) will retrieve the result of evaluating the
expression "1 + 2 + 3 + X()" -- which is "10".

The mechanism provides high-precision arithmetic, logical, and bitwise support
to preprocessor metaprogramming in *some* contexts--i.e. it cannot be used
*inside* a macro definition.

The mechanism is used primary in conjunction with the file-iteration support
provided by the preprocessor library. <-- also not part of an official release
yet.

The file-iteration support is basically a mechanism that uses a 'file' like it
is a macro, and 'macros' like they are arguments to a macro. It provides a
highly efficient mechanism to repeat text vertically--the compliment to
macro-recursion which can repeat text horizontally.

Back to the point, a macro similar to BOOST_PP_VALUE provides various arguments
to the file-iteration mechanism. This macro includes, among other things, and
upper and lower bound for the iteration. These values are evaluated in a way
similar to the way that the slots are. Because they are evaluated, you can do
simple arithmetic, logical expressions, and bitwise operations directly. E.g.

#define SOMETHING 10

#define FUNCTION_POINTER 0x0001
#define POINTER_TO_MEMBER 0x0002

#define BOOST_PP_ITERATION_PARAMS_1 \
4, (0, SOMETHING < 10 ? 1 : SOMETHING, file.hpp, 0x0004 | FUNCTION_POINTER)

// format: # of args, (lower bound, upper bound, file to iterate, flags)

I was hoping that I could use 'defined' in the context above. Either way, I can
still simulate it as long as the value isn't zero.

If you want to know more about this mechanism, email me privately. This is no
longer topical. :)

Paul Mensonides

0 new messages