geza
geza

Reputation: 29970

Is it possible to detect whether a local variable declared?

Is it possible to detect whether a local variable declared?

The reason is that I'd like to have a macro (LOG), which has a logic like this:

if (<logContext is declared>) {
    log(logContext, <parameters>);
} else {
    DefaultLogContext logContext(*this);
    log(logContext, <parameters>);
}

So, if the macro sees that there is a local variable named logContext, then it passes this variable to log. If logContext doesn't exist, then it creates a default logContext, and passes that to log.

Note: DefaultLogContext is a dependent type. It means that this logging macro can only be used in a class member function, and this type is a typedef to an actual type-dependent LogContext class:

class File {
    typedef FileLogContext DefaultLogContext;

    void open() {
        LOG("open"); // here, I'd like LOG to create a new local logContext
    }

    void complexFunction() {
        FileLogContext logContext(...);
        logContext.setup();

        LOG("pass1"); // here, I'd like LOG to use my declared logContext
        pass1();

        LOG("pass2"); // same comment as at pass1
        pass2();

        // other LOG and pass function calls here
};

Upvotes: 1

Views: 297

Answers (3)

user7860670
user7860670

Reputation: 37600

Somewhat ugly solution that checks for a presence of local variable named local_context:

#include <iostream>
#include <type_traits>

constexpr class t_Decoy{} const local_context; // should be declared in global scope
class t_Context{};

#define LOG(text) \
[&](char const * const psz_text) -> void \
{ \
  if constexpr(::std::is_same_v<t_Context, decltype(local_context)>) \
  { \ // we can use captured local_context here
     ::std::cout << psz_text << " has local_context" << ::std::endl; \
  } \
  else \
  { \ // we can create default context using captured this
     ::std::cout << psz_text << " no local_context" << ::std::endl; \
  }\
}(text)

int main()
{
    LOG("first");
    t_Context local_context{};
    LOG("second");
}

online compiler

Upvotes: 3

tenfour
tenfour

Reputation: 36896

You won't be able to do this via local variables. If you need an RAII style scoped logging facility, you have no choice but to create a local object explicitly.

LogScope logscope("some log msg");

If you don't need RAII, then you could have a global log object that maps __FUNCTION__ (or so) to a log context.

#define LOG(msg) { \
    auto& logScope = g_logManager[__FUNCTION__]; \
  }

Upvotes: 0

Lightness Races in Orbit
Lightness Races in Orbit

Reputation: 385264

No. Without reflection you cannot do such a thing autonomously. Then again, it would be of little benefit here.

Instead you should simply restructure your macros. You know, as the programmer, whether a variable is in scope at the point where you write your macro, and can instead use a different macro that does not require an extant variable.

Upvotes: 0

Related Questions