Saturday, January 21, 2017

Digest for comp.lang.c++@googlegroups.com - 22 updates in 5 topics

JiiPee <no@notvalid.com>: Jan 21 10:12AM

I hear experts all the time saying "dont use macros". But in my real
coding I see benefits sometimes using them. One is debugging/tracing
values in a debug mode:
 
 
Trace(x != 8, "x is wrong");
 
 
Using macro seems to be the only way to do this trace so that the
release version ignores that line and does not compile it. How would
"dont-use-macros" person do this other way?
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jan 21 12:21PM +0100

On 21.01.2017 11:12, JiiPee wrote:
 
> Using macro seems to be the only way to do this trace so that the
> release version ignores that line and does not compile it. How would
> "dont-use-macros" person do this other way?
 
There is no practical alternative to a macro for that, for example
because you then risk a stream of silly-warnings about dead code etc.,
warnings that you otherwise wouldn't want to disable.
 
That said there is tendency to think that since a macro must be involved
in this case, everything should be done with macros, like it's macros or
not macros, sort of George Bush-land: either you're with us, for
everything, or you're with the enemy, for everything.
 
Instead I suggest limiting the use of macros to the things that macros
are needed for, which in the above case are
 
• Code elimination when the checking is undesired (e.g. in release builds).
 
• Picking up the source location.
 
For the latter it can IMO be a good idea to define a class that
represents a source location, with a macro to create an instance.
 
I guess what I'm saying is the age old advice of separating concerns
also when it comes to use of macros. Don't think that because macros
evidently are needed, the whole problem area is macro-land. There are
just some pieces of the problem that require macros: these basic special
purpose macros can support much functionality that doesn't need to also
be expressed as macros.
 
 
Cheers & hth.,
 
- Alf
Hergen Lehmann <hlehmann.expires.5-11@snafu.de>: Jan 21 02:34PM +0100

Am 21.01.2017 um 12:21 schrieb Alf P. Steinbach:
 
>> release version ignores that line and does not compile it. How would
>> "dont-use-macros" person do this other way?
 
> There is no practical alternative to a macro for that,
 
An inline function should be able provide a very practical alternative
in this case:
 
inline void Trace(bool b,const char *s)
{
if (TraceMode && b) std::cout << s <<std::endl;
}
 
If TraceMode=false, the compiler should optimize that out without any
silly warnings and leftover dead code.
 
> just some pieces of the problem that require macros: these basic special
> purpose macros can support much functionality that doesn't need to also
> be expressed as macros.
 
Agreed.
 
Hergen
JiiPee <no@notvalid.com>: Jan 21 01:59PM

On 21/01/2017 11:21, Alf P. Steinbach wrote:
 
> There is no practical alternative to a macro for that, for example
> because you then risk a stream of silly-warnings about dead code etc.,
> warnings that you otherwise wouldn't want to disable.
 
But its not only about getting those trace-warnings but its also that
they slow down the runtime. Think about tracing that 10 milliona times
per second...
 
> involved in this case, everything should be done with macros, like
> it's macros or not macros, sort of George Bush-land: either you're
> with us, for everything, or you're with the enemy, for everything.
 
hehe
you have a point. Yes, I agree... and also the same thing I would say
with discussion with C-programmers. They say sometimes: "NONE of that
C++ is good at all... only C is good!!". But then C++ programmer can
also say: "everything must be C++, dont use functions , use
classes....always!!". I think its just that what works is
good....Although I dont see reason to use pure-old C only.. why not use
consts and those things?
 
> just some pieces of the problem that require macros: these basic
> special purpose macros can support much functionality that doesn't
> need to also be expressed as macros.
 
yes.
Also I found handy that that macro itself does not need to contain
variables but can be just a function call:
 
#define Trace(matrix) TraceFunc(matrix);
// and for release:
#define Trace
 
 
So intead of putting the matrix code inside the macro, we can just make
a normal function (TraceFunc) and call it from the macro. I think better
like this. so now:
 
int v=9;
 
Matrix m;
 
Trace(m);
 
...
 
Trace is only done for debug. otherwise we get TraceFunc(m);
JiiPee <no@notvalid.com>: Jan 21 02:05PM

On 21/01/2017 13:34, Hergen Lehmann wrote:
> }
 
> If TraceMode=false, the compiler should optimize that out without any
> silly warnings and leftover dead code.
 
oh, you might be right... never thought about that (optimizing)!
clever... compiler will see that this function is never run so it does
not compile it at all. But is this guaranteed?
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jan 21 03:26PM +0100

On 21.01.2017 14:34, Hergen Lehmann wrote:
> alternative in this case:
 
> inline void Trace(bool b,const char *s) { if (TraceMode && b)
> std::cout << s <<std::endl; }
 
Continuing the quote that you snipped mid-sentence:
 
>> dead code etc., warnings that you otherwise wouldn't want to disable.
 
 
> If TraceMode=false, the compiler should optimize that out without
> any silly warnings and leftover dead code.
 
Opinion doesn't trump actuality.
 
 
>> macros: these basic special purpose macros can support much
>> functionality that doesn't need to also be expressed as macros.
 
> Agreed.
 
 
[code]
#include <iostream>
 
namespace g{
bool const trace_mode = false;
} // namespace g
 
inline void trace( bool const b, char const* const s )
{
if( g::trace_mode and b ) { std::cout << s <<std::endl; }
}
 
auto main()
-> int
{
trace( true, "A" );
trace( false, "B" );
}
[/code]
 
[result]
[C:\my\forums\clc++\049]
> cl foo.cpp
foo.cpp
foo.cpp(9): warning C4127: conditional expression is constant
foo.cpp(7): warning C4100: 'b': unreferenced formal parameter
 
[C:\my\forums\clc++\049]
> _
[/result]
 
 
Cheers & hth.,
 
- Alf
Jorgen Grahn <grahn+nntp@snipabacken.se>: Jan 21 05:45PM

On Sat, 2017-01-21, JiiPee wrote:
> I hear experts all the time saying "dont use macros". But in my real
> coding I see benefits sometimes using them. One is debugging/tracing
> values in a debug mode:
 
Usually those experts mention exactly that exception (and include
guards). They just don't want C programmers to keep using macros for
tasks where C++ offers better alternatives.
 
/Jorgen
 
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Jan 21 05:53PM

On 21/01/2017 10:12, JiiPee wrote:
 
> Using macro seems to be the only way to do this trace so that the
> release version ignores that line and does not compile it. How would
> "dont-use-macros" person do this other way?
 
As long as the macro doesn't affect program behaviour (as is the case
here) then it is perfectly fine and is little different to using assert.
 
/Flibble
David Brown <david.brown@hesbynett.no>: Jan 21 07:00PM +0100

On 21/01/17 15:26, Alf P. Steinbach wrote:
 
>> If TraceMode=false, the compiler should optimize that out without
>> any silly warnings and leftover dead code.
 
> Opinion doesn't trump actuality.
 
Actuality with which compiler and options? The code you provide works
perfectly without extra warnings when I tried it with clang and gcc (-O2
-Wall -Wextra). It is a /long/ time since gcc warned about dead code
and constant conditionals, precisely because such warnings were so often
false.
 
And if you are really worried, you can write:
 
inline void trace( bool const b, char const* const s )
{
if( g::trace_mode and b ) {
std::cout << s <<std::endl;
} else {
std::ignore = b;
std::ignore = s;
}
}
 
That should avoid any warnings.
David Brown <david.brown@hesbynett.no>: Jan 21 07:03PM +0100

On 21/01/17 14:59, JiiPee wrote:
 
> #define Trace(matrix) TraceFunc(matrix);
> // and for release:
> #define Trace
 
Why not:
 
#ifdef DEBUG
 
static void Trace(int a) ....
 
#else
 
static inline void Trace(int a) {};
 

No comments: