Why this code must add sizeof()?

N

nevergone

Hello Everybody
In <<Modern C++ Design>> Compile-Time Assertions
there is :
template <bool> struct CompileTimeChecker
{
CompileTimeChecker(...);
};

template <> struct CompileTimeChecker<false> { };

#define STATIC_CHECK(expr,msg) \
{ \
class ERROR_##msg {}; \
(void)sizeof( CompileTimeChecker< (expr) !=
0>( (ERROR_##msg() ) )); \
}
//.....
so my question is why " (void)sizeof( CompileTimeChecker< (expr) !=
0>( (ERROR_##msg() ) )); \" must add sizeof?
Thanks
 
R

Ron Natalie

nevergone said:
so my question is why " (void)sizeof( CompileTimeChecker< (expr) !=
0>( (ERROR_##msg() ) )); \" must add sizeof?
Thanks
Sizeof is a handy function used in these kinds of macros because
it causes the syntax of the expression to be checked but never
actually evaluates the expression.
 
A

aiooua

so my question is why " (void)sizeof( CompileTimeChecker< (expr) != 0>( (ERROR_##msg() ) )); \" must add sizeof?

in general, checks for incomplete types are better done within sizeof
because it's runtime overheads are minimum. try to generate the
assembly code (using, g++ -S) with and without the "sizeof" and you'll
see that the sizeof version is better.

however, i have a related, but different problem. i tried the code as
printed in the book[#1] and couldn't get it to work.

---
/* begin code */
template<bool> struct CompileTimeChecker{ CompileTimeChecker(...); };
template<> struct CompileTimeChecker<false> { };
#define STATIC_CHECK(expr, msg) { class ERROR_##msg {};
(void)sizeof(CompileTimeChecker<(expr) != 0>((ERROR_##msg()))); }
int main(){ STATIC_CHECK(1>2,mustFail);}
/* end code */
---

here's what g++ gives me:

---
g++ -Wall -pedantic test.cpp
test.cpp: In function `int main()':
test.cpp:4: warning: ISO C++ forbids applying `sizeof' to a function
type
---

apart from that warning, the compilation goes through.
shouldn't it fail? what am i missing?

thanks,
 
N

nevergone

so my question is why " (void)sizeof( CompileTimeChecker< (expr) != 0>( (ERROR_##msg() ) )); \" must add sizeof?

in general, checks for incomplete types are better done within sizeof
because it's runtime overheads are minimum. try to generate the
assembly code (using, g++ -S) with and without the "sizeof" and you'll
see that the sizeof version is better.

however, i have a related, but different problem. i tried the code as
printed in the book[#1] and couldn't get it to work.

---
/* begin code */
template<bool> struct CompileTimeChecker{ CompileTimeChecker(...); };
template<> struct CompileTimeChecker<false> { };
#define STATIC_CHECK(expr, msg) { class ERROR_##msg {};
(void)sizeof(CompileTimeChecker<(expr) != 0>((ERROR_##msg()))); }
int main(){ STATIC_CHECK(1>2,mustFail);}
/* end code */
---

here's what g++ gives me:

---> g++ -Wall -pedantic test.cpp

test.cpp: In function `int main()':
test.cpp:4: warning: ISO C++ forbids applying `sizeof' to a function
type
---

apart from that warning, the compilation goes through.
shouldn't it fail? what am i missing?

thanks,
I don't know.
but i think it would be better to add () in 1>2
 
F

Fei Liu

nevergone said:
so my question is why " (void)sizeof( CompileTimeChecker< (expr) != 0>( (ERROR_##msg() ) )); \" must add sizeof?
in general, checks for incomplete types are better done within sizeof
because it's runtime overheads are minimum. try to generate the
assembly code (using, g++ -S) with and without the "sizeof" and you'll
see that the sizeof version is better.

however, i have a related, but different problem. i tried the code as
printed in the book[#1] and couldn't get it to work.

---
/* begin code */
template<bool> struct CompileTimeChecker{ CompileTimeChecker(...); };
template<> struct CompileTimeChecker<false> { };
#define STATIC_CHECK(expr, msg) { class ERROR_##msg {};
(void)sizeof(CompileTimeChecker<(expr) != 0>((ERROR_##msg()))); }
int main(){ STATIC_CHECK(1>2,mustFail);}
/* end code */
---

here's what g++ gives me:

---> g++ -Wall -pedantic test.cpp

test.cpp: In function `int main()':
test.cpp:4: warning: ISO C++ forbids applying `sizeof' to a function
type
---

apart from that warning, the compilation goes through.
shouldn't it fail? what am i missing?

thanks,
I don't know.
but i think it would be better to add () in 1>2
It's not necessary to add () in 1>2 except for readability reasons
(arguably since some people consider more () to be less readable). In
the macro, 'expr' is already guarded by ().

I found the code example confusing, it almost seemed like it should do a
sizeof(CompileTimeChecker<(expr)>) != 0 test instead. It may be trying
to facility the empty structure optimization, an empty struct/class's
sizeof returns 0 as the specialization template<> struct
CompileTimeChecker<false> { }; would do.

Fei
 
?

=?gb2312?B?stTxtw==?=

i got the same problem with aiooua
but if i took off the sizeof function
the code could work,but it seems that the compiler took the code
"CompileTimeChecker< (expr) >( (ERROR_##msg() ) )"
as a function declaration instead of a temporary object
here is my test code :

#include <iostream>
using namespace std ;
template <bool> struct CompileTimeChecker
{
CompileTimeChecker(...) { cout << "constructor" << endl ; }
};
template <> struct CompileTimeChecker<false> { };
#define STATIC_CHECK(expr,msg) \
{ \
class ERROR_##msg {}; \
CompileTimeChecker< (expr) >( (ERROR_##msg() ) ); \
}
int main()
{
STATIC_CHECK( true , error ) ;
return 0 ;
}
can anybody explain it ?
 
?

=?gb2312?B?stTxtw==?=

i think i got the answer:
suppose you have a class : class a { public : a(){} } ;
when you write the code : a() ;
the compiler can explain this in two ways:
1. a temporary object of type a
2. a function declaration of type a (*)(void)
so , in order to distinguish this you can use sizeof
which can not take a function type as a parameter
in order to tell sizeof that which you pass is a type
you have to add additional ()
so ,if you write sizeof( ( a() ) ) , the compiler will understand
that
a() is a temporary object
 
J

James Kanze

in general, checks for incomplete types are better done within sizeof
because it's runtime overheads are minimum. try to generate the
assembly code (using, g++ -S) with and without the "sizeof" and you'll
see that the sizeof version is better.
however, i have a related, but different problem. i tried the code as
printed in the book[#1] and couldn't get it to work.
---
/* begin code */
template<bool> struct CompileTimeChecker{ CompileTimeChecker(...); };
template<> struct CompileTimeChecker<false> { };
#define STATIC_CHECK(expr, msg) { class ERROR_##msg {};
(void)sizeof(CompileTimeChecker<(expr) != 0>((ERROR_##msg()))); }

I'm not sure about the exact error message you got---it seems a
little strange. But this line is definitly illegal; for
starters, it contains a } for which there is no {. And ##
operators are only legal in macros.

Are you sure you didn't forget a \ at the end of the previous
line? This line would make sense as part of the macro.
int main(){ STATIC_CHECK(1>2,mustFail);}
/* end code */
---
here's what g++ gives me:
---> g++ -Wall -pedantic test.cpp
test.cpp: In function `int main()':
test.cpp:4: warning: ISO C++ forbids applying `sizeof' to a function
type

Which, as I say, is wierd. The only way a compiler could
possibly parse the sizeof here is as part of an expression
statement. (But of course, expression statements are not legal
at namespace scope.)

Note that if you did mean for this line to be part of the macro,
the line number in the error message should tip you off
immediately about the forgotten \. You never get error messages
from continuation lines in a macro. (Just error messages from
where you invoke the macro.)
apart from that warning, the compilation goes through.
shouldn't it fail? what am i missing?

Probably just an \.
 
A

aiooua

however, i have a related, but different problem. i tried the code as
printed in the book[#1] and couldn't get it to work.
---
/* begin code */
template<bool> struct CompileTimeChecker{ CompileTimeChecker(...); };
template<> struct CompileTimeChecker<false> { };
#define STATIC_CHECK(expr, msg) { class ERROR_##msg {};
(void)sizeof(CompileTimeChecker<(expr) != 0>((ERROR_##msg()))); }
Are you sure you didn't forget a \ at the end of the previous
line? This line would make sense as part of the macro.

the macro was well-formed when i compiled, it got wrapped into two
lines (maybe because of line-length limits or something) while i
posted it here.
I'm not sure about the exact error message you got---it seems a

unlike what the book says, and what i expected i did not get any
error.
however, i got the following warning.

--
test.cpp:4: warning: ISO C++ forbids applying `sizeof' to a function
type
--

it seemed too simple to be a g++ bug, but i'll follow it on their
newsgroup.

thanks,
 
D

Default User

aiooua wrote:

unlike what the book says, and what i expected i did not get any
error.
however, i got the following warning.

The ISO C++ standard does not mandate "warnings" or "errors". Certain
conditions require a diagnostic. A warning is a diagnostic. It is quite
possible for a compiler to decide to continue with compilation,
especially if operating in a non-conforming mode so that it applies
various extensions.





Brian
 
J

James Kanze

however, i have a related, but different problem. i tried the code as
printed in the book[#1] and couldn't get it to work.
---
/* begin code */
template<bool> struct CompileTimeChecker{ CompileTimeChecker(...); };
template<> struct CompileTimeChecker<false> { };
#define STATIC_CHECK(expr, msg) { class ERROR_##msg {};
(void)sizeof(CompileTimeChecker<(expr) != 0>((ERROR_##msg()))); }
Are you sure you didn't forget a \ at the end of the previous
line? This line would make sense as part of the macro.
the macro was well-formed when i compiled, it got wrapped into two
lines (maybe because of line-length limits or something) while i
posted it here.

You mean that the line following the #define was actually on the
same line?

The reason I asked is because when I added the \ to the end of
the line with the #define, the code worked as expected (i.e.
failed to compile). (Of course, without the \, it failed to
compile as well.)
unlike what the book says, and what i expected i did not get any
error.
however, i got the following warning.

If I add the \ to the end of the line, I get:
cerr.cc: In function 'int main()':
cerr.cc:5: error: invalid application of 'sizeof' to a function
type
from g++. Both with no options, and with my usual options.
Maybe you have set some option somewhere to make g++ treat this
as a warning only.
 

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,780
Messages
2,569,611
Members
45,280
Latest member
BGBBrock56

Latest Threads

Top