• 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.

8 replies to this topic

### #1floatingwoods  Members

364
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
}

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

### #2Zaoshi Kaba  Members

7782
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  Members

20244
Like
5Likes
Like

Posted 17 December 2013 - 02:46 PM

POPULAR

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)

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.

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.

### #4floatingwoods  Members

364
Like
0Likes
Like

Posted 17 December 2013 - 03:07 PM

Thanks to both of you, that's briliant!

3479
Like
5Likes
Like

Posted 17 December 2013 - 03:31 PM

POPULAR

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;
}

### #6Servant of the Lord  Members

33484
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.  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' or 'SotL' rather than copy+pasting it all the time.
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.
Of Stranger Flames -

### #7Vortez  Members

2705
Like
1Likes
Like

Posted 17 December 2013 - 07:43 PM

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

Or just code a normal function for that???

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

### #8ChaosEngine  Members

4744
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

### #9floatingwoods  Members

364
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.