Jump to content

  • Log In with Google      Sign In   
  • Create Account


conditional statement + automatic clean-up in preprocessor command


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
8 replies to this topic

#1 floatingwoods   Members   -  Reputation: 290

Like
0Likes
Like

Posted 17 December 2013 - 12:31 PM

Hello,

 

I wish to have a conditional statement, followed immediately by an object instanciation that will automatic clean-up at the end of a scope, a little bit similar to following example:

if (conditionRealized)
{
    // do something
}

which effectively would translate into something like:

if (conditionRealized)
{
    DummyObject dummy(initializationType);
    // do something
}

in above example, the destructor of dummy can automatically clean-up various things.

I have to place such a construct into several hundreds of functions, and I wish to simplify the task with a preprocessor command, so that I will be able to write:

IF_CONDITION_REALIZED_THEN
{
    // do something
}

but above construct does obviously not work, since the scope comes after the preprocessor command.

I could use a preprocessor like:

#define IF_CONDITION_REALIZED_THEN if(conditionRealized) { DummyObject dummy(initializationType);

in order to write my code like:

IF_CONDITION_REALIZED_THEN
    // do something
}

but my code editor doesn't like this (puts wrong indents), and it looks ugly.

 

Any idea?

 

Or, to present my problem in a different light:

 

I have a condition, that if passed, needs to make sure something is executed at the end of the scope, similar to this example:

if (canLockOtherThreads())
{
    // do something
    unlockOtherThreads();
}

Edited by floatingwoods, 17 December 2013 - 12:40 PM.


Sponsor:

#2 Zaoshi Kaba   Crossbones+   -  Reputation: 3435

Like
3Likes
Like

Posted 17 December 2013 - 01:00 PM

You can do that with for() loop that does only single cycle:

#define IF_CONDITION_REALIZED_THEN for(DummyObject dummy(initializationType); conditionRealized; conditionRealized = false)

though it'll modify conditionRealized variable.



#3 Álvaro   Crossbones+   -  Reputation: 11710

Like
5Likes
Like

Posted 17 December 2013 - 02:46 PM

If you can do the cleanup with a free function instead of a destructor, here's one possibility:

#include <iostream>

#define IF_WITH_CLEANUP(X) for (bool dummy_boolean = (X); dummy_boolean; unlockOtherThreads(), dummy_boolean = false)

void unlockOtherThreads() {
  std::cout << "Unlocked!\n";
}

int main() {
  bool condition = true;
 
  IF_WITH_CLEANUP (condition)
    std::cout << "Write something\n";
}

Although I would hate you if you did something like that in code that I have to work with. smile.png

 

EDIT: Sooner or later someone will write a `continue' or `break' inside the conditional block and we'll have some fun debugging it.


Edited by Álvaro, 17 December 2013 - 02:48 PM.


#4 floatingwoods   Members   -  Reputation: 290

Like
0Likes
Like

Posted 17 December 2013 - 03:07 PM

Thanks to both of you, that's briliant!



#5 Adam_42   Crossbones+   -  Reputation: 2355

Like
5Likes
Like

Posted 17 December 2013 - 03:31 PM

Here's another slightly less nasty way to do it. It involves modifying (or wrapping) the auto destructing class so it holds the result of the condition, and declaring a variable inside the if statement:
 

class hack
{
private:
    bool m_cond;

public:
    hack(bool cond, int x) : m_cond(cond) { cout << "hack()" << x << endl; }
    ~hack() { cout << "~hack()" << endl; }

    operator bool() { return m_cond; }
};

#define HACKY_IF(cond, value) if (hack h = hack(cond, value))
 
int main()
{
    HACKY_IF(true, 42)
    {
        cout << "bar" << endl;
    }

    cout << "main end" << endl;
}


#6 Servant of the Lord   Crossbones+   -  Reputation: 16724

Like
3Likes
Like

Posted 17 December 2013 - 04:16 PM

This also works:

#include <iostream>
using namespace std;

class Test
{
	public:
	Test(bool condition) : condition(condition)
	{
		if(condition)
		{
			std::cout << "if(condition) special init needs" << std::endl;
		}
	}
	
	~Test()
	{
		if(condition)
		{
			std::cout << "if(condition) special cleanup needs" << std::endl;
		}
	}
	
	operator bool() { return condition; }
	
	private:
	bool condition = false;
};

#define DoIf(cond) if(Test DoIf_test = Test(cond))

int main()
{
	std::cout << "Start of main" << std::endl;
	
	DoIf(true)
	{
		std::cout << "Inside condition A" << std::endl;	
	}
	
	DoIf(false)
	{
		std::cout << "Inside condition B" << std::endl;	
	}
	
	std::cout << "End of main" << std::endl;	
	
	return 0;
}

This is legal, afaik, but I'm not sure if the lifetime of assignments within conditionals is standardized.

Compilable example

 

Some static code analyzers will complain about assignments within if() statements as warnings, because it'll think you're actually wanting if(i == 0) but are accidentally using if(i = 0).

 

[Edit:] Uh, ninja'd by almost an hour. rolleyes.gif I had to refine and test my work several times before I got it working, initially going the lambda route which, while functional, had too many limitations and syntax messiness.


Edited by Servant of the Lord, 17 December 2013 - 04:21 PM.

It's perfectly fine to abbreviate my username to 'Servant' rather than copy+pasting it all the time.

[Fly with me on Twitter] [Google+] [My broken website]

All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.                                                                                                                                                       [Need free cloud storage? I personally like DropBox]

Of Stranger Flames - [indie turn-based rpg set in a para-historical French colony] | Indie RPG development journal


#7 Vortez   Crossbones+   -  Reputation: 2687

Like
1Likes
Like

Posted 17 December 2013 - 07:43 PM

Why not just put that 'special condition' in the object destructor instead? blink.png

 

Or just code a normal function for that???


Edited by Vortez, 17 December 2013 - 07:48 PM.


#8 ChaosEngine   Crossbones+   -  Reputation: 2111

Like
1Likes
Like

Posted 18 December 2013 - 06:01 AM

Just a note that all the above suggestions (the for loop back, etc.) are not exception safe.

As a general rule, I'd advise against this kind of macro. It's non-idiomatic, error prone and difficult to debug.

C++ already has a perfectly valid cleanup mechanism in RAII. Trust me, saving a bit of typing is just not worth it

Edit: oops, missed servants post. That is exception safe, still wouldn't use the macro though.
if you think programming is like sex, you probably haven't done much of either.-------------- - capn_midnight

#9 floatingwoods   Members   -  Reputation: 290

Like
0Likes
Like

Posted 18 December 2013 - 06:53 PM

A lot of good ideas, thanks a lot to all of you!






Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS