easily throw away c++ call completely - c++

I'm trying to implement logging which produce no overhead when not needed (i.e. no method call should be performed at all). I want NO overhead because it's low-latency code. I just added #define ENABLE_LOGS to my header class and now it looks like that (you can ignore details)
#pragma once
#include <string>
#include <fstream>
#define ENABLE_LOGS
namespace fastNative {
class Logger
{
public:
Logger(std::string name_, std::string fileName, bool append = false);
~Logger(void);
void Error(std::string message, ...);
void Debug(std::string message, ...);
void DebugConsole(std::string message, ...);
void Flush();
static Logger errorsLogger;
static Logger infoLogger;
private:
FILE* logFile;
bool debugEnabled;
};
}
Every time I need to use some method I should surround it like that:
#ifdef ENABLE_LOGS
logger.Debug("seq=%6d len=%4d", seq, length_);
#endif
It's error-phrone (i can forgot to surround) and makes code dirty. Can I fix my code somehow not to use #ifdef every time?
In C# I like Conditional I guess I need something like that for c++.

First of all it would make sense to have a look to see what's out there already. This is a common problem and many people will have solved it before. E.g., see stackoverflow question C++ logging framework suggestions, and Dr Dobbs A Highly Configurable Logging Framework In C++.
If you do roll your own, you should get some good ideas from having done this. There are several approaches I've used in the past. One is to make the statement itself conditionally defined
#ifdef ENABLE_LOGS
#define LOG(a,b,c) logger.Debug(a, b, c)
#else
#define LOG(a,b,c)
#endif
Another approach is to conditionally define the logging class itself. The non-logging version has everything as empty statements, and you rely on the compiler optimizing everything out.
#ifdef ENABLE_LOGS
class Logger
{
public:
Logger(std::string name_, std::string fileName, bool append = false);
~Logger(void);
void Error(std::string message, ...);
void Debug(std::string message, ...);
void DebugConsole(std::string message, ...);
void Flush();
static Logger errorsLogger;
static Logger infoLogger;
private:
FILE* logFile;
bool debugEnabled;
};
#else
class Logger
{
public:
Logger(std::string name_, std::string fileName, bool append = false) {}
~Logger(void) {}
void Error(std::string message, ...) {}
void Debug(std::string message, ...) {}
void DebugConsole(std::string message, ...) {}
void Flush() {}
};
#endif
You could put your Logger implementation for ENABLE_LOGS in a cpp file under control of the macro. One issue with this approach is that you would want to be sure to define the interface so the compiler could optimize everything out. So, e.g., use a C-string parameter type (const char*). In any case const std::string& is preferable to std::string (the latter ensures there's a string copy every time there's a call).
Finally if you go for the first approach, you should encapsulate everything in do() { ... } while(0) in order to ensure that you don't get bizarre behavior when you use your macro where a compound statement might be expected.

There is one way (the way llvm does) to do this using macros.
#ifdef ENABLE_LOGS
#define DEBUG(ARG) do { ARG; } while(0)
#else
#define DEBUG(ARG)
#endif
Then use it as:
DEBUG(logger.Debug("seq=%6d len=%4d", seq, length_););

What I often see, is to use the #define to actually define the log calls, eg:
#define LOG_DEBUG(msg) logger.Debug(msg);
But you want to wrap the defines in a block that enables or disables your logging:
#ifdef ENABLE_LOGS
#define LOG_DEBUG(msg) logger.Debug(msg);
#else
#define LOG_DEBUG(msg)
#endif
You can call LOG_DEBUG anywhere in your code. If the logging is disabled, calling LOG_DEBUG ends up as a blank line in your final code.

A nice old trick is:
#ifdef ENABLE_LOGS
#define LOG Logger.Debug
#else
#define LOG (void)sizeof
#endif
Then the code:
LOG("seq=%6d len=%4d", seq, length_);
will expand to:
Logger.Debug("seq=%6d len=%4d", seq, length_);
that does the log. Or:
(void)sizeof("seq=%6d len=%4d", seq, length_);
that does absolutely nothing. It doesn't even evaluate the function arguments!!!
The trick is that the first version uses the comma as argument separator in a function call. In the second version, however, it is a unevaluated comma operator.
However, some compilers may give spurious warnings about unreachable code.

You could put the #ifdef inside the body of the individual functions. This avoid the code duplication issue in TooTone's answer.
Example:
void fastNative::Logger::Debug(std::string message, ...)
{
#ifdef ENABLE_LOGS
// do the actual logging
#endif
}
If ENABLE_LOGS isn't defined, this function doesn't do anything. What I would suggest is you pass a const char* instead of std::string to these method. That way, if ENABLE_LOGS is not defined, you wouldn't have to rely on the compiler to not create redundant std::string objects.

Related

How to define a macro that resolves to either method name or no operation?

In the code base I have many sections that are either turned on or off depending on enabled features. The aim is to generate program code as small as possible (Arduino with 32kB program memory).
Lets say I have the code as below:
class A
{
private:
#ifdef FEATURE
int m_optA;
int m_optB;
#endif
public:
#ifdef FEATURE
void SetFeatureOptions(int optionA, int optionB)
{
m_optA = optionA;
m_optB = optionB;
}
#endif
};
#ifdef FEATURE
#define SETFEATUREOPTIONS(a, b) SetFeatureOptions(a, b)
#else
#define SETFEATUREOPTIONS(a, b) Noop() // ????? <-- what should I put here to perform NOOP
#endif
class B
{
public:
A m_a;
void DoStuff()
{
// approach 1:
#ifdef FEATURE
m_a.SetFeatureOptions(1, 34);
#endif
// approach 2:
// Lets have a macro - see above
// This way each time I want to call SetFeatureOptions but only when FEATURE is defined
// I need no ifdef/endif scope to be used explicitely.
m_a.SETFEATUREOPTIONS(1, 34);
}
}
Is there a way to resolve SETFEATUREOPTIONS macro so it compiles and yet doesn't generate any code, when called as a method name?
Why way is to implement Noop() method in class A, but I was wondering if there is better way, that is not requiring adding a null method like mentioned above Noop(). I am not sure if adding inline Noop(){} will add some bytes to the program memory or not (Release, optimized code).
IMPORTANT: This has to compile with C++98 compiler.
Just write:
void SetFeatureOptions(int optionA, int optionB)
{
#ifdef FEATURE
m_optA = optionA;
m_optB = optionB;
#endif
}
and make sure you compile with optimizations turned on. Your compiler is smart enough to delete the function call, if the function is defined in the header file and is empty.
If the function is defined in a different .cpp file the compiler won't know it's empty, so it won't delete the call.

Is there any way to change function prototypes at compile time in C++?

suppose you have to write code that should compile under C++,C++11,C++17,etc.
A function like this for example.
bool Ispalindrome(const std::string &str)
{
// Code
}
That compiles under all C++ implementations. But if you want to use the old and the new the C++17 string_view feature you have deal with something similar to
#ifdef LEGACYCPP
bool Ispalindrome(const std::string &str)
{
// Code
}
#elseif CPP17
bool Ispalindrome(std::string_view str)
{
// OMG Repeated Code
}
#endif
Using conditional compiling is right, but have to repeat code.
Is there any way to choose a function prototype at compile time ? Or other way to circumvent double coding ? (in situations where it can be applied)
Thanks
In a header file, you'll need to do something like
#if __cplusplus >= 201703L
#include <string_view>
bool Ispalindrome(std::string_view str);
#else
#include <string>
bool Ispalindrome(const std::string &str);
#endif
In your definition, you'll need to include the header and then do
#if __cplusplus >= 201703L
bool Ispalindrome(std::string_view str)
#else
bool Ispalindrome(const std::string &str)
#endif
{
// OMG no repeated code
}
__cplusplus is specified in the standard, and is predefined in every compilation unit. 201703L indicates a C++17 compiler, larger values more recent standards.
This assumes an implementation (compiler and library) that correctly claims compliance with the respective C++ standard.
If you can be sure that the code section of your function will be equivalent in each case, then you can use a macro definition for the parameter list:
#ifdef ISCPP17
#define PALIN_PARAMS std::string_view str
#else
#define PALIN_PARAMS const std::string& str
#endif
bool Ispalindrome(PALIN_PARAMS)
{
// Code
}
#undef PALIN_PARAMS
There are, of course, many variations on this theme: you could leave out the "str" part in the macro definition and have (PALIN_PARAMS str) in the signature. But, using "as is" will also allow for multiple parameters with different types.
But I'm not sure this sort of thing will pass the Inquisitions of the C++ Puritans.
Another (possibly more robust) way would be to use conditional compilation blocks with using (or typedef) statements to define argument types:
#ifdef ISCPP17
using cnststrg = std::string_view; // Or typedef std::string_view cnststrg;
#else
using cnststrg = const std::string&;
#endif
bool Ispalindrome(cnststrg str)
{
// Code
return true;
}
Provided it's exactly repeated code then, do following minor change:
#ifdef CPP17
bool Ispalindrome(std::string_view str)
#else // all versions of LEGACYCPP
bool Ispalindrome(const std::string &str)
#endif
{
// Same Code
}
If a minor part of function is unique to versions, then apply the above same trick there too.

C/C++ aliasing functions to other function with different arguments

The following is some background as to what I want to do and why. The actual question is at the very bottom...
I have an API that has some format.
For instance
int f(void *str1, void *str2) {...}
I want to reimplement the system behind the API so that it can be a drop in replacement for the old system. However it turns out that str1 is now unnecessary and moreover doesn't make sense to have if you're aware that you're using my new system. Therefore, I want to be able to expose the underlying API that makes sense:
int f_internal(void *str2);
Right now I have code that looks like this:
#ifdef USE_INTERNAL
#define INTERNAL(sym) sym##_internal
#else
#define INTERNAL(sym) sym
#endif
extern "C" {
#ifndef USE_INTERNAL
int f(void *str1, void *str2){
return INTERNAL(f)(str2);
}
#endif
SOME_ATTRIBUTES
int
INTERNAL(f)(void *str2){
... // actual content
} EXPORT_FUNCTION_MACRO(INTERNAL(f), 1);
}
The effect is if I define USE_INTERNAL, a call to f(a) works, but I don't define it then we have to use the f(a, b).
The problem I am encountering is that EXPORT_FUNCTION_MACRO itself defines another function name but doesn't evaluate INTERNAL(F) first. This results in the message
dir: error: pasting ")" and "_" does not give a valid preprocessing token
INTERNAL(sym) \
--- NOTE--- EXPORT_FUNCTION_MACRO takes args 'sys' and 'n'
other_dir: note: in definition of macro ‘EXPORT_FUNCTION_MACRO’
void _example##sym##_##n(void) {} \
WHAT I WANT TO DO:
I want to have a compile flag that can change the number of arguments needed to call something.
Maybe something like (if it existed)
using f(a, b) = f_internal(a);
Any ideas?
This results in the message
To fix the message let macro arguments expand before concatenating them.
#define EXPORT_FUNCTION_MACRO_X(sys, n) EXPORT_FUNCTION_MACRO(sys, n)
EXPORT_FUNCTION_MACRO_X(INTERNAL(f), 1);
You could achieve that with a macro in the C part:
#define f(...) CONCAT(f, NUM(__VA_ARGS__, 2, 1)) (__VA_ARGS__)
#define CONCAT(X, Y) CC(X, Y)
#define CC(X, Y) X ## Y
#define NUM(X, Y, N, ...) N
#ifdef __cplusplus
extern "C"
#endif
void f_internal(void* str);
// specifically compiled for C or C++ anyway (and most likely inlined)
// -> no need for extern "C" for these:
void f1(void* str) { f_internal(str); }
void f2(void* unused, void* str) { f_internal(str); }
The macro f would select the correct function out of f1 and f2, which again would call f_internal with the correct argument. Works for both C and C++. If you prefer, you could still just provide two overloads for C++ separately and let only the C people deal with the macros.
I doubt one could call that 'elegant'; if you want to qualify as 'ugly' – up to you. But at least it works...
The following code behaves like this:
If USE_INTERNAL is defined, defines an inline (c++) / static (c) function int f(void* str).
Otherwise, defines an inline (c++) / static (c) function int f(void* str1, void* str2).
Both functions are trampolines to the actual (int f_internal(void* str)) function.
Note that since the functions are defined in the header, inline (c++) / static (c) is required to keep them from violating the ODR rule (I am a c++ person, so I don't know any way better than static to achieve this in c. If there is, please let me know).
#ifdef __cplusplus
extern "C"
#endif
int f_internal(void* str);
#ifdef USE_INTERNAL
#ifdef __cplusplus
inline
#else
static
#endif
int f(void* str1, void* str2) {
return f_internal(str2);
}
#else
#ifdef __cplusplus
inline
#else
static
#endif
int f(void* str) {
return f_internal(str);
}
#endif

Replace 'Define macro' with empty implementation

I usually use the #define macro to add code that will be here while compiling as debug time and not while compiling as release. For instance:
#ifdef NDEBUG
# define LOG(msg) (void)msg
#else
# define LOG(msg) MyDebugLogger(msg)
#endif
Instead of that, I was thinking of using plain function and, just not providing the body for the release method:
void MyDebugLogger(std::string const& msg);
In MyDebugLogger.cpp:
void MyDebugLogger(std::string const& msg)
{
#ifdef NDEBUG
std::clog << msg << "\n"; // Or whatever
#else
(void)msg;
#endif
}
I'm expecting that the compilers will have the power to strip out the call and add no extra cost in Release. Am I correct?
For some reason, could it be a bad practice?
EDIT: My question is: If I use macros as before, I know that in Release mode, the executable will be smaller and faster, as all the code has been removed.
If I use the function, will it be the same? As the compiler may understand that the function does nothing and is not necessary. (Or it will add an extra, even small, for calling an empty function)
practically you would do the same as with the macro:
void MyDebugLogger(std::string const& msg)
{
#ifdef NDEBUG
std::clog << msg << "\n"; // Or whatever
#endif
}
You'r example should work, with a little tweak. In your current version the compiler "sees" just the function signature and will emit a call to it's symbol, which will later be resolved via the linker, so it can't optimize it out on it's own. (Link Time Optimizations might help with that, but that depends very much on you'r setup and dynamic linking would make this impossible). So maybe try something like this
in the header:
// Assuming you are using clang or gcc,
// but is required to not give an error by the standard and probably
// not even needed.
[[gnu::always_inline]]
void MyDebugLogger(std::string const& msg [[maybe_unused]])
{
#ifdef NDEBUG
MyDebugLoggerImplementation(msg);
#endif
}
And then implement it in you .cpp file. Another benefit of this method is that you
method needs the Logger to be compiled with NDEBUG while this method gives the client code the choice.

C++ performance, optimizing compiler, empty function in .cpp

I've a very basic class, name it Basic, used in nearly all other files in a bigger project. In some cases, there needs to be debug output, but in release mode, this should not be enabled and be a NOOP.
Currently there is a define in the header, which switches a makro on or off, depending on the setting. So this is definetely a NOOP, when switched off. I'm wondering, if I have the following code, if a compiler (MSVS / gcc) is able to optimize out the function call, so that it is again a NOOP. (By doing that, the switch could be in the .cpp and switching will be much faster, compile/link time wise).
--Header--
void printDebug(const Basic* p);
class Basic {
Basic() {
simpleSetupCode;
// this should be a NOOP in release,
// but constructor could be inlined
printDebug(this);
}
};
--Source--
// PRINT_DEBUG defined somewhere else or here
#if PRINT_DEBUG
void printDebug(const Basic* p) {
// Lengthy debug print
}
#else
void printDebug(const Basic* p) {}
#endif
As with all questions like this, the answer is - if it really matters to you, try the approach and examine the emitted assembly language.
Compiler possibly may optimize this code, if it knows printDebug function implementation at compilation time. If printDebug is in another object module, this possibly may be optimized only by linker, using the whole program optimization. But the only way to test this is to read compiler-generated Assembly code.
If you already have PRINT_DEBUG macro, you can extend it by the way as TRACE is defined:
#define PRINT_DEBUG // optional
#ifdef PRINT_DEBUG
#define PRINT_DEBUG_CALL(p) printDebug(p)
#else
#define PRINT_DEBUG_CALL(p)
#endif
void printDebug(const Basic* p);
class Basic {
Basic() {
simpleSetupCode;
// this should be a NOOP in release,
// but constructor could be inlined
PRINT_DEBUG_CALL(this);
}
};
--Source--
// PRINT_DEBUG defined somewhere else or here
#if PRINT_DEBUG
void printDebug(const Basic* p) {
// Lengthy debug print
}
#endif
#if PRINT_DEBUG
#define printDebug _real_print_debug
#else
#define printDebug(...)
#endif
This way the preprocessor will strip all debug code before it even gets to the compiler.
Currently most of the optimizations are done at compile time. Some compilers as LLVM are able to optimize at link time. This is a really interesting idea. I suggest you to take a look at.
Waiting for these kind of optimization, what you can do is the following. Define a macro that let you include the following statement depending on whether DEBUG is defined or not.
#ifdef DEBUG
#define IF_DEBUG (false) {} else
#else
#define IF_DEBUG
#endif
You can the use it like this
Basic() {
simpleSetupCode;
// this should be a NOOP in release,
// but constructor could be inlined
IF_DEBUG printDebug(this);
}
which is already much more readable than
Basic() {
simpleSetupCode;
// this should be a NOOP in release,
// but constructor could be inlined
#if DEBUG
printDebug(this);
#endif
}
Note that you can use it as if it was a keyword
IF_DEBUG {
printDebug(this);
printDebug(thas);
}
errm, why not use the pre-processor macro differently?
Just of the top of my head, something like:
#define DEBUG_TRACE(p)
#ifdef PRINT_DEBUG
printDebug(p);
#else
;
#endif