Reputation: 29970
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
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");
}
Upvotes: 3
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
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