Jump to content
  • Advertisement
Sign in to follow this  
irreversible

Is there a trickier way to write this?

This topic is 646 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have a simple shorthand macro for debugging, which looks like this:

#define if_once(_name) static boolean _name = true; if(_name && !(_name = false))

Which I use as:

if_once(myonce) {
 ... do stuff once ...
}

The problem is that it generates a C4706 (assignment within conditional expression in VS). 

 

Here's my Neanderthal approach to the problem:

 

I really like my macro - it's convenient, especially when I need to prototype stuff fast.

I don't want to change its apparent syntax (eg whatever goes in the macro body is fair game as long as it doesn't affect the if_once(myonce) { } part, meaning that the curly braces must stay outside the macro body).

I don't want to add a warning disable-default pragma block around each use since that completely defeats the purpose of a shorthand.

I definitely don't want to disable the warning globally.

 

Therefore, since I don't want to include a curly brace in the macro body or write cryptic dual block guards, I can't think of a way to write it without an assignment in the if body.

 

Any brilliant ideas how to swindle the compiler?

 

Share this post


Link to post
Share on other sites
Advertisement

I hate it when an answer smacks in you in the face literally as soon as you finish writing a question on a public forum...

 

I suppose one can just write it as:

 

#define if_once(name) static boolean name = false; if(!name && ++name)

 

:wacko:

Share this post


Link to post
Share on other sites

I will not ask as to why you would want something so ugly and with such a massive bad smell in your code base, might as well store all your data in global variables as well :)

I would not be including such code anywhere near any code base I worked on and would be asking whoever added something like it to remove it and think about what they were trying to achieve and a better solution.

Share this post


Link to post
Share on other sites

I will not ask as to why you would want something so ugly and with such a massive bad smell in your code base, might as well store all your data in global variables as well :)

I would not be including such code anywhere near any code base I worked on and would be asking whoever added something like it to remove it and think about what they were trying to achieve and a better solution.

 

 

Actually, that's precisely what this is for - managing globals during brainstorming.

 

I've accumulated a substantial codebase by now, which means it's much faster and easier for me to start writing new components in-situ in order to have minimal compile times and the least possible code spread. In these circumstances I generally iterate a lot and often; in fact, for me this kind of an approach is actually less error-prone as I will have a lot fewer unused parameters and convoluted code around after I'm done sketching out the basics and feel good enough about moving the new stuff into a more established environment. For instance, I might start out by keeping everything in the render loop until the thing I want to do actually works, or I get a better idea in which case I can quickly scrap it without hunting through headers and other code files for associated clutter. In particular, something like this restricts initializing all the what would otherwise be temporary globals into a named block, which is far easier to gauge by eye.

 

Mind you, I don't keep any such code lying around after I'm done sketching up the basics, nor am I promoting using something like this in a serious production :). Instead, this allows me to blurt whatever is in my head out there faster and test it without worrying about formalizing it every step of the way. If it works, I will have a clean block of code that I know to purge.

 

Otherwise this isn't even code smell - it's fire hazard.

Share this post


Link to post
Share on other sites
#define if_once(name) static boolean name = false; if(!name && ++name)

Using the increment operator on an operand of type bool has been deprecated since at least C++03. Possibly earlier, but I do no longer keep a copy of C++98 around, so cannot check. That being said, why are you using a type boolean instead of the proper keyword? This is C++ as per the question's tag, right?

 

You could opt to use std::call_once which does what you want and is in addition thread-safe. Unless of course, you already know no threads are involved and you fear the performance implications of thread-safety (but then you can implement your own thread-unsafe version, taking the std version as a starting point). Note that using the keyword static at function scope guarantees thread-safe initialization anyway, so there is not much to fear performance-wise (you're already paying the price!).

 

The to-be-executed code can stay in-place as a lambda, just add a couple of braces.

 

Bonus points:

(1) if you later decide to refactor, and want to move the code to a separate function, it's simple. Remove captures and add params instead so the code still works. Can do that one by one, and the code still works the same. Once done, copy-paste the lambda and give it a name.

(2) you do not get ODR-violations like you will get with your macro if you ever have two instances of if_once. But I'll admit that this can probably be fixed with an extra pair of braces, or with a __LINE__ hack that gives the boolean an unique name. Still, it's one of these unexpected not-immediately-obvious surprises that make macros so nasty.

Edited by samoth

Share this post


Link to post
Share on other sites
Using the increment operator on an operand of type bool has been deprecated since at least C++03.

 

I was actually about to look into that, but since VS didn't even so much as sneeze at it, it seemed low priority.

 

 

 

why are you using a type boolean instead of the proper keyword? This is C++ as per the question's tag, right?

 

 

Because I like my syntax hilighting the way it is. The two types are equivalent.

 

 

 

Note that using the keyword static at function scope guarantees thread-safe initialization anyway, so there is not much to fear performance-wise (you're already paying the price!).

 

 

While valid points, this, everything about name clashes and the entire paragraph in general, in my case, is overthinking it. As mentioned, this is nothing more than a debugging aid while sketching out a new piece of functionality. In fact, the macro is disabled in release build.

Edited by irreversible

Share this post


Link to post
Share on other sites

Usually, compilers allow you to override that assignment-in-if warning by placing an extra pair of parens around the assignment expression. So:

#define if_once(_name) static boolean _name = true; if(_name && !((_name = false)))

I would avoid the solutions based on the “++tag” thing. ++'ing a bool has been deprecated since forever and it will be removed completely in C++17.

Edited by Oxyd

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!