Jay
Jay

Reputation: 2946

Is it possible to explicitly redefine a local variable

I have a macro for calling a function and logging that the call was made

#define LogHandle(message,function) {Log(message + #function); function;}

The function also returns if it was successful or not, i can use a member variable like

#define LogHandle(message,function) {Log(message + #function); m_lastLogHandleResult = function;}

Then in code do

LogHandle("Tried to do sometheing",Func())
if(m_lastLogHandleResult) {/* more code */}

but this approach would be quite difficult to thread-safe

ideally id want to do something like

#define LogHandle(message,function) bool result; {Log(message + #function); result = function;}

but this causes issues if i try to use this macro twice within a scope as it's re-defining a local

is it possible to explicitly redefine a local variable? like

new bool result;

Edit: As comments suggest could put each call to this function within a scope {}, which is not a bad solution, but ideally i'd like to be able to not do this

Upvotes: 1

Views: 97

Answers (2)

You can play preprocessor tricks to often have a unique variable name.

An example from my Bismon software:

#define LOCALRETURN_ATLIN_BIS_BM(Lin,Res) do {      \
  struct stackframe_stBM*prevfram_##Lin             \
    = _.__frame.stkfram_prev;                       \
  ASSERT_BM (prevfram_##Lin                         \
      && ((typedhead_tyBM *)prevfram_##Lin)->htyp   \
      == typayl_StackFrame_BM);                     \
  prevfram_##Lin->stkfram_callfun = NULL;           \
  return (value_tyBM)(Res);                         \
 } while(0)

#define LOCALRETURN_ATLIN_BM(Lin,Res) LOCALRETURN_ATLIN_BIS_BM(Lin,Res)
#define LOCALRETURN_BM(Res) LOCALRETURN_ATLIN_BM(__LINE__,(Res))

I would use LOCALRETURN_BM(x) and it gets expanded to something unique by GNU cpp using concatenation and sometimes stringizing.

RefPerSys has similar tricks at end of 2020, and you could use some better preprocessor like GPP.

You can also generate C++ code appropriately

You could also design your own C++ code generator, with inspiration from SWIG or Qt moc. Tools like ANTLR or GNU bison are then helpful. You would configure your build automation tool (e.g. your Makefile for GNU make). See also GNU autoconf and GNU m4.

With GNU cpp specifically, you can use not only __LINE__ but also __COUNTER__

See also this related answer that you could generalize to emission of C++ code. Your C++ code generator might even emit #line directives.

Upvotes: 1

Some programmer dude
Some programmer dude

Reputation: 409176

I would implement it using a combination of macros and functions.

A macro so we can get the function "name", which calls a function passing the "name" and which returns the result to be tested.

Perhaps something like this:

#define LogHandle(message, function, ...) LogHandleHelper(message, function, #function, __VA_ARGS__)

template<typename R, typename F, typename... A>
R LogHandleHelper(std::string const& message, F function, std::string function_name, A&&... arguments)
{
    Log(message + function_name);
    return function(std::forward<A>(arguments)...);
}

Could then be used as:

if (LogHandle("Tried to do sometheing", Func))
{
    // Special case code here...
}

[Note: Untested. might need tweaks to get it working]

Upvotes: 3

Related Questions