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
};
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
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.
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__]; \
}
Related
I am working on a RAII class that should be able to trace the code-flow of a function. It should be able to capture the line number of the function when it is constructed and do the same when it is destructed. The macros __FILE__ and __LINE__ would not work since they are substituted at the time of call. This rules out the following approach:
#define PRINT_LINES \
struct LineRecorder \
{ \
LineRecorder() { std::cout << __LINE__; } \
~LineRecorder() { std::cout << __LINE__; } \ <- Substitutes the line number at macro call
} {};
C++20 has support for source location which works at compile-time. This led me to the approach:
struct LineRecorder
{
LineRecorder(std::source_location location = std::source_location::current())
{
std::cout << location.line();
}
~LineRecorder(std::source_location location = std::source_location::current())
// destructor can't take any arguments (not even default ones)
{
std::cout << location.line();
}
};
Some other approaches that didn't pan out:
Since source_location.current is marked constexpr, it should be evaluated before any inlining is done: that rules out any lambda trickery I could think of.
I plan to use it inside performance sensitive code, so should ideally not add any run-time overhead: this rules out stacktrace parsing. The std::cout in the code above is just a (very very) expensive placeholder.
Is there any way this can be achieved?
You can’t do this: the main reason is that ~T can be called from many places other than the } of a block. Among those are various parts of the constructor of any type that contains a subobject of type T, any evaluation that might throw out of a block that contains a local T variable, a new T[n] expression (for n>1), or the end of a thread or process. C++20 adds coroutine_handle::destroy as an indirect means of causing destruction.
None of these have a good “What line is this?” answer. The fact that our syntactic trick of a default argument (which is a bit silly anyway) doesn’t work is at most a corollary.
Consider the pair of functions below:
double MYAPI foo(double x) {
return x;
}
Register register_foo_([] {
return reg(&foo, "foo", ...); // function name repeated used
});
register_foo_ is a global variable, initialized before dllmain, whose constructor takes a lambda that repeatedly references the name of the function above it literally. It would be great if the registration code can move inside the function above to reduce the chance of making an error. I tried:
double MYAPI foo(double x) {
static Register register_foo_([] {
return reg(&foo, "foo", ...); // static local does not initialize before dllmain
});
return x;
}
If the above code works, then I can easily turn it into a macro that makes use of __FUNCNAME__. Is there a way to force the initialization of static local variable register_foo_ before dllmain?
Static variables local to a function (method) are initialized on first use of the function they're in. (They're zero-initialized at program load, then initialized "properly" via code when the function is first entered.) See the answers to this question. So your proposed movement of that code into the function changes the semantics of initialization, and it won't work.
Your original code worked, so what you apparently wanted was to move the code inside the function so it was somehow tied closer together in your mind - or the mind of a reader of the code - so that you could see that your string constant name and function name were right. Also maybe so that you could ensure the registration was done. And therefore what you want is to accomplish DRY.
The traditional (and only) way to accomplish that is by using a preprocessor macro that expands into the registration call and the function header.
You proposed using a macro yourself - now expand the macro so it not only generates the registration function but also the function header.
I suppose you want to achieve a syntax similar to:
DEFINE_FUNC(void, foo, (double x)) {
return x;
}
... and have the boilerplate autogenerated. That's actually very simple to do if you bring the Register above the function, with the help of a declaration:
#define DEFINE_FUNC(Ret, name, args) \
Ret name args; \
Register register_##name##_([] { \
return reg(&name, #name, ...); \
}); \
Ret name args
No, there's not. That's your answer.
I'm reading gflags's source code recently. And the comment here really confuses me.
It's saying FLAGS_nono##name is introduced to ensure static initialization. But as far as I know, if you define a global var like:
int x = 20;
x is still statically initialized. The what's the necessity of FLAGS_nono##name here.
Do I misunderstand it?
Thanks.
// Each command-line flag has two variables associated with it: one
// with the current value, and one with the default value. However,
// we have a third variable, which is where value is assigned; it's a
// constant. This guarantees that FLAG_##value is initialized at
// static initialization time (e.g. before program-start) rather than
// than global construction time (which is after program-start but
// before main), at least when 'value' is a compile-time constant. We
// use a small trick for the "default value" variable, and call it
// FLAGS_no<name>. This serves the second purpose of assuring a
// compile error if someone tries to define a flag named no<name>
// which is illegal (--foo and --nofoo both affect the "foo" flag).
#define DEFINE_VARIABLE(type, shorttype, name, value, help) \
namespace fL##shorttype { \
static const type FLAGS_nono##name = value; \
/* We always want to export defined variables, dll or no */ \
GFLAGS_DLL_DEFINE_FLAG type FLAGS_##name = FLAGS_nono##name; \
type FLAGS_no##name = FLAGS_nono##name; \
static #GFLAGS_NAMESPACE#::FlagRegisterer o_##name( \
#name, #type, MAYBE_STRIPPED_HELP(help), __FILE__, \
&FLAGS_##name, &FLAGS_no##name); \
} \
using fL##shorttype::FLAGS_##name
For more context, see
https://code.google.com/p/gflags/source/browse/src/gflags.h.in#471
Another question is the FlagRegisterer class used in the codes mentioned above.
I'm wondering what's the necessity of such class and a global var here, instead of simply defining a function.
class GFLAGS_DLL_DECL FlagRegisterer {
public:
FlagRegisterer(const char* name, const char* type,
const char* help, const char* filename,
void* current_storage, void* defvalue_storage);
};
// --------------------------------------------------------------------
// FlagRegisterer
// This class exists merely to have a global constructor (the
// kind that runs before main(), that goes an initializes each
// flag that's been declared. Note that it's very important we
// don't have a destructor that deletes flag_, because that would
// cause us to delete current_storage/defvalue_storage as well,
// which can cause a crash if anything tries to access the flag
// values in a global destructor.
// --------------------------------------------------------------------
FlagRegisterer::FlagRegisterer(const char* name, const char* type,
const char* help, const char* filename,
void* current_storage, void* defvalue_storage) {
if (help == NULL)
help = "";
// FlagValue expects the type-name to not include any namespace
// components, so we get rid of those, if any.
if (strchr(type, ':'))
type = strrchr(type, ':') + 1;
FlagValue* current = new FlagValue(current_storage, type, false);
FlagValue* defvalue = new FlagValue(defvalue_storage, type, false);
// Importantly, flag_ will never be deleted, so storage is always good.
CommandLineFlag* flag = new CommandLineFlag(name, help, filename,
current, defvalue);
FlagRegistry::GlobalRegistry()->RegisterFlag(flag); // default registry
}
You're right that something like int i = 10; performs static initialisation. It would therefore be possible to write
#define DEFINE_VARIABLE(type, shorttype, name, value, help) \
namespace fL##shorttype { \
/* We always want to export defined variables, dll or no */ \
GFLAGS_DLL_DEFINE_FLAG type FLAGS_##name = value; \
type FLAGS_no##name = value; \
static #GFLAGS_NAMESPACE#::FlagRegisterer o_##name( \
#name, #type, MAYBE_STRIPPED_HELP(help), __FILE__, \
&FLAGS_##name, &FLAGS_no##name); \
} \
using fL##shorttype::FLAGS_##name
However, please beware that this is a macro. Multiple references to value cause multiple expansions. If value is not a constant, if it contains e.g. a function call, this would cause the function to be called twice.
That could be avoided by copying one variable to the other:
#define DEFINE_VARIABLE(type, shorttype, name, value, help) \
namespace fL##shorttype { \
/* We always want to export defined variables, dll or no */ \
GFLAGS_DLL_DEFINE_FLAG type FLAGS_##name = value; \
type FLAGS_no##name = FLAGS_##name; \
static #GFLAGS_NAMESPACE#::FlagRegisterer o_##name( \
#name, #type, MAYBE_STRIPPED_HELP(help), __FILE__, \
&FLAGS_##name, &FLAGS_no##name); \
} \
using fL##shorttype::FLAGS_##name
But now you've got dynamic initialisation, where you'd want static initialisation.
To make sure both work properly, you need an additional helper variable, and that's what the code you're asking about does.
Is this even possible? I would like to write a macro that makes it easier to use some of my classes functionality.
Lets say I have 2 member functions in my class, setup() and cleanup(), where setup() sets up parameters for some operation that needs to be executed in its own scope, and cleanup() preforms cleanup (similar to a constructor and destructor concept).
Currently, I do this:
myClassInstance.setup(); //call the setup function
{ //start scope
//CREATE LOCAL VARS
//DO STUFF IN THIS SCOPE
myClassInstance.cleanup(); //cleanup
} //end scope, destroy locals
But would like to do something like this instead:
NEWSCOPE(myClassInstance) //calls setup()
{
//CREATE LOCAL VARS
//DO STUFF IN THIS SCOPE
} // calls cleanup() and destroys locals
My thought was to write a macro class that can be instantiated when the macro is used and setup() and cleanup() could be implemented in the constructor/destructor... or something like that...
Is this the right way to think about this or is there another way to write a macro that can essentially wrap around code written by the user?
* EDIT *
I fixed the naming convention as the function names were causing come confusion.
To create a new scope just use an anonymous block.
{
Obj obj;
/*
teh codez
*/
}//obj is deallocated
So you don't need a macro
It also sounds like you startScope and endScope should actually be constructor and destructor but once again it's hard to know without knowing what they actually do
UPDATE: I tried to give you an answer but instead I'll just rant.
similar to a constructor and destructor concept
To me that sounds like they are constructors and destructors, when you have the constructor and destructor doing the setup and cleanup the operations will be performed naturally and readably with RAII.
Another thing, you say your first solution (which I sort of accidentally gave back to you) is working, why workaround with a macro, in C macros were needed to simulate features (like templates, and objects) that C++ provides. For almost every situation, especially with C++11, macros will only make things worse and harder to debug, also in your case it seems like you actually have to type more when you do the macro?
My suggestion is rethink why you need to have a macro and why setup and cleanup can't be a constructor and destructor.
You might treat this in the same way as you would acquire a mutex lock with RAII. Something like this:
class MyClassScopeBlock
{
public:
MyClassScopeBlock( MyClass & c )
: obj(c)
{
obj.startScope();
}
~MyClassScopeBlock()
{
obj.endScope();
}
private:
MyClass & obj;
};
Then instantiate that as a local variable inside a scope block:
{
MyClassScopeBlock block( myClassInstance );
//CREATE LOCAL VARS
//DO STUFF IN THIS SCOPE
}
And if you really want, you can define a macro for it, to be used inside the scope block:
#define NEWSCOPE(inst) MyClassScopeBlock block(inst)
Personally, I prefer to stay away from macros whenever possible.
I spent hours trying to figure out how to make a Macro control a scope after seeing the BOOST_FOREACH Macro. In the process of figuring it out I ran across this question hoping it held the answer! But, not quite. So, I read through all of the code for the BOOST_FOREACH and the original design for BOOST_FOREACH. Then I felt kind of dumb... A Macro essentially inserts the code directly where it is placed. This means that we can have a Macro:
#define LOOP_3() \
for(int i = 0; i < 3; ++i)
Now, let us test it out!
LOOP_3() std::cout << "Hello World!" << std::endl;
/* === Output ===
Hello World!
Hello World!
Hello World!
*/
Yay! But, how is this useful? Well, at the end of the loop what happens to i?
The destructor is called which for i is not too fancy, but the idea is there.
All we need now is a class to handle this:
class SCOPE_CONTROL {
public:
SCOPE_CONTROL(): run(1) { std::cout << "Starting Scope!" << std::endl; }
~SCOPE_CONTROL() { std::cout << "Ending Scope!" << std::endl; }
bool run;
}
Let us put that sucker to use!
#define NEWSCOPE() \
for(SCOPE_CONTROL sc = SCOPE_CONTROL(); sc.run; sc.run = 0)
...
NEWSCOPE()
std::cout << " In the Body!" << std::endl;
std::cout << "Not in body..." << std::endl;
...
/* === Output ===
Starting Scope!
In the Body!
Ending Scope!
Not in body...
*/
To use the setup and cleanup functions, just change a small bit!
class SCOPE_CONTROL {
public:
SCOPE_CONTROL(MyClass myClassInstance): control(myClassInstance), run(1) {
control.setup();
}
~SCOPE_CONTROL() { control.cleanup(); }
bool run;
MyClass & control;
}
#define NEWSCOPE(control) \
for(SCOPE_CONTROL sc = SCOPE_CONTROL(control); sc.run; sc.run = 0)
...
NEWSCOPE(myClassInstance)
{
// CREATE LOCAL VARS
// DO STUFF IN THIS SCOPE
} // end scope, destroy locals
...
To make it even better use the ENCODED_TYPE (how to make in the design for BOOST_FOREACH very simple!) to allow SCOPE_CONTROL to be a template type.
A better alternative to putting the entire scope inside the macro replacement is to use something like a finally block. I've had success encapsulating the linked solution with these macros:
#define FINALLY_NAMED( NAME, ... ) auto && NAME = \
util::finally( [&]() noexcept { __VA_ARGS__ } );
#define FINALLY( ... ) CPLUS_FINALLY_NAMED( guard, __VA_ARGS__ )
#define DO_FINALLY static_cast< void >( guard );
usage:
{
myClassInstance.setup(); //call the setup function
FINALLY ( myClassInstance.cleanup(); ) //call the cleanup function before exit
// do something
DO_FINALLY // Explicitly note that cleanup happens here. (Only a note.)
}
This is exception-safe, and cleanup executes if and only if setup completes successfully, just like a constructor/destructor pair. But the the cleanup must not throw exceptions.
But if you want to do it the old-fashioned way…
You can contain the entire scope inside the macro by using variadic macros:
#define NEWSCOPE( INSTANCE, ... ) { \
(INSTANCE).setup(); /* call the setup function */ \
{ __VA_ARGS__ } /* paste teh codez here */ \
(INSTANCE).cleanup(); /* call the cleanup function */
I would recommend against putting cleanup inside the internal scope because the point of a scope is to contain declarations and names, but you want to use the name of INSTANCE from the outer scope.
usage:
NEWSCOPE ( myClassInstance,
// Do stuff.
// Multiple declarations, anything can go here as if inside braces.
// (But no #define directives. Down, boy.)
)
I have a class that has no default constructor, but the constructor may throw. I was wanting to have a test like:
EXPECT_THROW(MyClass(param), std::runtime_error);
But the compiler, g++, complains that there is no default constructor for MyClass. However, the following...
EXPECT_THROW(MyClass foo(param), std::runtime_error);
...works, and the test passes as expected. Why though won't Googletest accept the temporary object?
class MyClass
{
public:
MyClass(std::string const& filename);
//...
};
Interestingly enough, I had refactored my test to not have the filename in a separate variable, and when asked to check I found the following works:
EXPECT_THROW(MyClass("somefilename"), std::runtime_error);
However the following doesn't:
std::string filename("somefilename");
EXPECT_THROW(MyClass(filename), std::runtime_error);
If you're hit with the "most vexing parse", the cure is often uniform initialization:
EXPECT_THROW(MyClass{param}, std::runtime_error);
(assuming your compiler understands C++11).
When dealing with macros, ultimate tool is analyzing expanded macro:
In your case (and for gtest 1.6):
EXPECT_THROW(MyClass(filename), std::runtime_error);
Expands to:
...
bool gtest_caught_expected = false; \
try { \
if (::testing::internal::AlwaysTrue()) { MyClass(filename); }; \
} \
catch (std::runtime_error const&) { \
gtest_caught_expected = true; \
} \
catch (...) { \
gtest_msg.value = \
"Expected: " "MyClass(filename)" " throws an exception of type " \
"std::runtime_error" ".\n Actual: it throws a different type."; \
goto gtest_label_testthrow_88; \
} \
if (!gtest_caught_expected) { \
gtest_msg.value = \
"Expected: " "MyClass(filename)" " throws an exception of type " \
"std::runtime_error" ".\n Actual: it throws nothing."; \
goto gtest_label_testthrow_88; \
} \
...
As you can see, argument to EXPECT_THROW is not object, but expression to be evaluated further, within GTEST provided valid try/catch block.
So anything you pass to it, must be able to evaluate as expression within nested scope of current scope. In your case:
MyClass(filename)
Is ambiguous, but according to Most vexing parse rule, declaration interpretation is preferred, so you end up with:
MyClass filename
So you are creating variable named filename of class MyClass - and hence error about missing constructor.
This mechanism is not triggered if you use literal string:
MyClass("some string")
Becouse following would be invalid (and there is no ambiguity):
MyClass "some string"
Can you give more information? I constructed an example which works fine with a class that only has a one argument constructor.
#include <iostream>
#include <stdexcept>
#include "gtest/gtest.h"
class m {
public:
m(std::string a) {std::cout << "one argument constructor" << std::endl;}
};
int main() {
EXPECT_THROW(m("hat"), std::runtime_error);
}
Output:
one argument constructor
gtt.cc:12: Failure
Expected: m("hat") throws an exception of type std::runtime_error.
Actual: it throws nothing.
EDIT
I do not claim to be an expert on the arcane inner-workings of the C/C++ pre-processor, but I think this has to do with the rules followed when evaluating expressions, in particular, in the land of the pre-processor, parentheses are king. When the pre-processor evaluates MyClass(filename) it first evaluates filename which produces a temporary value which is immediately discarded, it then evaluates MyClass(). Calling MyClass("filename") causes the pre-processor to actually copy the literal string into the expression. One way around this problem is to call EXPECT_THROW((MyClass(filename)), std::runtime_error), i.e. use a set of enclosing parentheses around your statement.