Compile only for debug?

B

Bob Altman

Hi all,

I'm hoping someone can suggest a clever way that I can cause a function call
to become a noop when the user builds the Release configuration. Here's the
whole sordid story...

I've created a function that operates like cout except that it directs its
output to a file. Users write to the file using this syntax:

dout << "Text" << number << endl;

Like cout, dout is actually a global variable. The header file that defines
it looks like this (much simplified):

class DebugMessage
{
public:
template <class T> DebugMessage& operator<<(const T& param) {
[implementation] }
}

// Define an external reference to the dout global object
extern DebugMessage dout;

The dll that exposes my DebugMessage class also exports the global dout
object.

Ok, enough background. Now, my issue: I can't just #define dout to make it
go away, because the compiler will choke on the "<< parameters..." part of
the statement. I could create a DebugMessageNoop global object whose "<<"
operator does nothing, and conditionally define dout as either an instance
of DebugMessage or an instance of DebugMessageNoop based on whether the
_DEBUG symbol exists, but that means I need to implement another class and
the callers still get stuck with the overhead of calling into a do-nothing
routine for each "<<" operator.

Is there some way that I can do some #define magic to make the caller's dout
and all of the gibberish to the right of it go away if the _DEBUG symbol
doesn't exist?

TIA - Bob
 
C

Charles Wang[MSFT]

Hi Bob,
To let me better understand your issue, could you please post some of your
code snippets here so that we can reproduce your issue and perform
effective research? If you do not want to post publicly, you can send an
email to me (changliw_at_microsoft_dot_com).

Best regards,
Charles Wang
Microsoft Online Community Support
=====================================================
When responding to posts, please "Reply to Group" via
your newsreader so that others may learn and benefit
from this issue.
======================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
======================================================
 
D

David Wilkinson

Bob said:
Hi all,

I'm hoping someone can suggest a clever way that I can cause a function call
to become a noop when the user builds the Release configuration. Here's the
whole sordid story...

I've created a function that operates like cout except that it directs its
output to a file. Users write to the file using this syntax:

dout << "Text" << number << endl;

Like cout, dout is actually a global variable. The header file that defines
it looks like this (much simplified):

class DebugMessage
{
public:
template <class T> DebugMessage& operator<<(const T& param) {
[implementation] }
}

// Define an external reference to the dout global object
extern DebugMessage dout;

The dll that exposes my DebugMessage class also exports the global dout
object.

Ok, enough background. Now, my issue: I can't just #define dout to make it
go away, because the compiler will choke on the "<< parameters..." part of
the statement. I could create a DebugMessageNoop global object whose "<<"
operator does nothing, and conditionally define dout as either an instance
of DebugMessage or an instance of DebugMessageNoop based on whether the
_DEBUG symbol exists, but that means I need to implement another class and
the callers still get stuck with the overhead of calling into a do-nothing
routine for each "<<" operator.

Is there some way that I can do some #define magic to make the caller's dout
and all of the gibberish to the right of it go away if the _DEBUG symbol
doesn't exist?

Bob:

If your NoOp method is defined inline maybe there is no overhead?
 
B

Ben Voigt [C++ MVP]

Is there some way that I can do some #define magic to make the
caller's dout and all of the gibberish to the right of it go away if
the _DEBUG symbol doesn't exist?

Well, first we've got to ask whether "make the caller's dout and all of the
gibberish to the right of it go away" is an accurate description of what you
want. What if that stuff had side effects?

int* p;
int length;

int index = 0;
while (index < length)
dout << p[index++] << ", ";
dout << "END" << endl;

Making the whole line involving dout "go away" is probably not what you
want, it would turn perfectly good code into an infinite loop.

So perhaps what you want is to make the insertion operator do nothing.
That's easy enough to accomplish by placing #if _DEBUG/#endif in the body.
 
B

Bob Altman

Well, first we've got to ask whether "make the caller's dout and all of the
gibberish to the right of it go away" is an accurate description of what you
want. What if that stuff had side effects?

int* p;
int length;

int index = 0;
while (index < length)
dout << p[index++] << ", ";
dout << "END" << endl;

Making the whole line involving dout "go away" is probably not what you want,
it would turn perfectly good code into an infinite loop.

Hmmm... I didn't think of that. I guess you're right--I need to preserve side
effects, so the best I can do is to conditionally eliminate the code in the "<<"
operator function.

I guess there's no way to eliminate the call into the "<<" function from the
compiler's perspective. But I'll bet that if I define the "<<" operator as
"inline" then the resultant code (with the body of the function conditionally
eliminated) will be as efficient as if the "<<" operator function wasn't there
at all.

Which raises a new question: Is there a way to use the "inline" qualifier in a
separate code file, or must I always use it in code that exists in the class
header file? In other words:

in x.h:

class X {
inline void abc() {} // This works
};

but, in a separate file (abc.cpp)

inline void X::abc() {} // Error
 
B

Bob Altman

Which raises a new question: Is there a way to use the "inline" qualifier
in a separate code file, or must I always use it in code that exists in
the class header file? In other words:

in x.h:

class X {
inline void abc() {} // This works
};

but, in a separate file (abc.cpp)

inline void X::abc() {} // Error

Never mind... After thinking it over, I guess it kind of makes sense that
the compiler can't "inline" code that is compiled into a separate
compilation unit. (However, the docs say that "inline" is only a suggestion
to the compiler, and I see no reason why the compiler couldn't put some
linker directives in the object to ask the linker to grab the code from the
compiled "inline" routine and insert it into the calling routine.)
 
B

Ben Voigt [C++ MVP]

Bob said:
Never mind... After thinking it over, I guess it kind of makes sense
that the compiler can't "inline" code that is compiled into a separate
compilation unit. (However, the docs say that "inline" is only a
suggestion to the compiler, and I see no reason why the compiler
couldn't put some linker directives in the object to ask the linker
to grab the code from the compiled "inline" routine and insert it
into the calling routine.)

This is "Whole Program Optimization" which VC 2005/2008 do support.

Of course you can probably use:

class X {
void abc()
#ifdef _DEBUG
;
#else
{}
#endif
};

You might have to also #ifdef the implementation in the other file, or the
linker may just not use it because the compiler found the inline definition.
 

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

Top