marsh
marsh

Reputation: 2730

#define not executing all arguments

I am having trouble with a #define I have made. For some reason it is not checking all the arguments in the statement.

THROW_AND_LOG(Foo::Initialize() && Bar::Initialize() && FooBar::Initialize(), "Something() could not Initialize singletons.");

For some reason it is only initializes Foo and then exits the statement. It does not throw or log.

However

THROW_AND_LOG((Foo::Initialize() && Bar::Initialize() && FooBar::Initialize()), "Something() could not Initialize singletons.");

works fine for some reason. (Wrapped all the checks in brackets).

I am going to move everything on to its own seperate line to fix this as its not the best code in the first place. I am curious however of why it would not execute all statements.

Here is the define:

#define THROW_AND_LOG(x, message) if(!x) { throw std::runtime_error(message);              \
    LOG::v1::MessageSender messageSender("log");                                           \
    LOGGING_ERROR(messageSender,message);}

Upvotes: 0

Views: 63

Answers (3)

Anton Savin
Anton Savin

Reputation: 41301

After the macro expansion,

if(!x)

transforms to

if(!Foo::Initialize() && Bar::Initialize() && FooBar::Initialize())

Foo::Initialize() presumably returns true, so !Foo::Initialize() is false and other terms are not executed (not mentioning that their meaning has changed to the opposite).

Upvotes: 7

Cheers and hth. - Alf
Cheers and hth. - Alf

Reputation: 145279

With the macro definition

#define THROW_AND_LOG(x, message) if(!x) { throw std::runtime_error(message);              \
    LOG::v1::MessageSender messageSender("log");                                           \
    LOGGING_ERROR(messageSender,message);}

the invocation

THROW_AND_LOG(Foo::Initialize() && Bar::Initialize() && FooBar::Initialize(), "Something() could not Initialize singletons.");

yields the condition

if(!Foo::Initialize() && Bar::Initialize() && FooBar::Initialize())

which is equivalent to

if((!Foo::Initialize()) && Bar::Initialize() && FooBar::Initialize())

A good fix is to replace the macro with a function:

void throw_and_log_if(
     const bool          condition,
     const Location&     location,
     const string&       message )
{
    LOG::v1::MessageSender messageSender( "log" );
    LOGGING_ERROR( messageSender, message ); }
    throw std::runtime_error( message );
}

where Location is some class representing file and line number, which you can pick up via the __FILE__ and __LINE__ macros.

I took the liberty of fixing the bug causing logging to not be performed.


A short term easier fix is to use parenthesis around the x in the macro's condition.

If you choose that, then do remember to fix the bug in the macro.

Upvotes: 3

Carl Norum
Carl Norum

Reputation: 224964

It's not expanding the way you think it is. You want (!(x)) in your macro.

Upvotes: 6

Related Questions