I am currently adapting a Windows C++ project to make it work on Linux. I defined several macros to print formatted lines to a log file. They are printf-like so I can write this:
WARN("%d::%s<", 42, "baz");
It's pretty easy to print something like:
[thread_id][WARN][/path/to/main.cpp:15][Fri 03/01/2019 10:38:54.408][this_value] 42::baz<
this_value
is value of this or NULL if this is not defined (static function, extern "C" function).
My current code is:
#if defined(_WIN32) && !defined(__INTELLISENSE__)
#define SET_ZIS __if_exists (this) { zis = this; }
#else
#define SET_ZIS
#endif
#define _LOG(...) \
do \
{ \
void *zis = NULL; \
SET_ZIS \
GetLoggerInstance()->logMessage(__VA_ARGS__); \
} while(0)
#define LOG(...) _LOG(level, __FILE__, __LINE__, __func__, zis, __VA_ARGS__)
#define WARN(...) LOG(ILogger_level::LEVEL_WARN, __VA_ARGS__)
Is there a standard way to detect if this exists?
Maybe using std::is_*
or a SFINAE trick ?
I use extern-ed "C" functions to construct objects ("this" is meaningless) and call members on instanciated objects ("this" is meaningful). "Constructors" are exported in a shared object and dynamically consumed by a C++ project. Doing it that way, I don't have to manage mangled names.
extern "C" int CreateMyClass(std::shared_ptr<MyClass> *newClass);
int CreateMyClass(std::shared_ptr<MyClass> *newClass)
{
RELAY("(%p)", newClass);
*newClass = std::make_shared<MyClass>(42, "baz");
return 0;
}
MyClass::MyClass(int a, char *b)
{
RELAY("(%d,%s)", a, b);
}
EDIT: Here's a simple test case:
#include <memory> /* For std::shared_ptr */
#define RELAY(...) printf("[%p][%s]\n", this, __func__)
class MyClass
{
public:
MyClass(int a, const char *b);
static void test();
};
extern "C" int CreateMyClass(std::shared_ptr<MyClass> *newClass);
int CreateMyClass(std::shared_ptr<MyClass> *newClass)
{
RELAY("(%p)", newClass);
*newClass = std::make_shared<MyClass>(42, "baz");
return 0;
}
MyClass::MyClass(int a, const char *b)
{
RELAY("(%d,%s)", a, b);
}
void MyClass::test()
{
RELAY("()");
printf("some work");
}
int main(int argc, char **argv)
{
std::shared_ptr<MyClass> newClass;
int ret = CreateMyClass(&newClass);
MyClass::test();
return ret;
}
g++ gives the following errors:
test.c: In function ‘int CreateMyClass(std::shared_ptr<MyClass>*)’:
test.c:2:41: error: invalid use of ‘this’ in non-member function
#define RELAY(...) printf("[%p][%s]\n", this, __func__)
^
test.c:14:3: note: in expansion of macro ‘RELAY’
RELAY("(%p)", newClass);
^~~~~
test.c: In static member function ‘static void MyClass::test()’:
test.c:2:41: error: ‘this’ is unavailable for static member functions
#define RELAY(...) printf("[%p][%s]\n", this, __func__)
^
test.c:26:3: note: in expansion of macro ‘RELAY’
RELAY("()");
^~~~~
CreateMyClass
is not static ("non-member function"), so this is unavailable. Same thing for the static function.