I have simple delegate functions in my C++ test code. Since I cannot include the original implementation .cpp files(embedded ones), I use delegate .cpp file in the tests that are running on PC. My idea is to simply use the same macro as a body for the implementation, except the parentheses () and arguments which will supplied according to the signature.
I tried something like:
void Flash::init()
{
DELEGATE_DESTINATION();
}
bool Flash::write(args)
{
DELEGATE_DESTINATION(args);
}
bool Flash::read(args)
{
DELEGATE_DESTINATION(args);
}
Where
void Flash::init()
bool Flash::write(args)
bool Flash::read(args)
Are identical to the ones in the embedded project implementation ones. In the test files I simply relay the call to the fake implementations. One possible solution would be to already include the signature and implementation in the fake classes not using relaying, I know.
I am having hard time figuring out the macro. I tried something like:
#define FAKE_PREFIX fakes::device::Flash::
#define DELEGATE_DESTINATION FAKE_PREFIX##__FUNCTION__
Which expands to FAKE_PREFIX__FUNCTION__
Well then after going through C Preprocessor, Stringify the result of a macro
I can get only fakes expanding in place.
My goal would be to have a result like
fakes::device::Flash::init
and so on for read and write.
What you want to do can be done far simpler. You don't need the full power of the pre-processor:
You don't concatenate tokens (:: is not part of a valid token). You just need to print one macro next to another.
_FUNCTION_ isn't a pre-processor macro, it's a string literal (in gcc and other compilers).
So to do what you want, you need to pass the function name into your macro:
#define FAKE_PREFIX fakes::device::Flash::
#define DELEGATE_DESTINATION(func) FAKE_PREFIX func
Then you define your functions, like this:
bool Flash::write(args)
{
DELEGATE_DESTINATION(write)(args);
}
It's all live here.
Related
Suppose I have this:
// test.h
namespace test {
#define TEST_DEBUG !NDEBUG
class TestClass {
#if TEST_DEBUG
// ...
#endif
};
}
The problem is that other files that include test.h will also get the TEST_DEBUG macro, which is not ideal.
If I use #undef at the end of the header, then that means I can't use the macro in test.cpp.
What would be the best way to solve this issue?
Although I'd advise avoiding macros in C++ (eg this could be replaced with a bool parameter to the function), the simplest way to achieve this is to define TEST_DEBUG in test.cpp before including test.h, and removing it from test.h.
A #include directive is replaced by the c preprocessor similar to a "copy the contents of that file here" way. This copy is repeated each time the #include appears. This also means if there's something defined before the #include appears in one file, but that's not defined in another, then things may break in unpredictable ways (because eg one file thinks an object is bigger than another file thinks it is).
However, to give more idiomatic c++, for a compile time flag you can use bool constexprs. Alternatively, for a runtime change, if it's a class, pass a bool to the constructor to indicate the difference, a function can have an extra parameter that defaults to false, etc.
I don't know what this concept is called, so title may sound weird. Imagine the following scenario:
main.cpp:
#define SOME_KEYWORD
int main()
{
foo();
return 0;
}
other.cpp:
void foo()
{
//Do some stuff
#ifdef SOME_KEYWORD
//Do some additional stuff
#endif
}
I've tried it out and it doesn't work if #define is present in other file. Is there a way around this? (I'd rather not to modify function parameters just to achieve this, since it will only be present at development time and functions can be many layers of abstraction away.)
And, I guess this is a C way to do things, I don't know if that would be considered as a good practice in C++, if not, what are the alternative ways?
In c++, from c++17, a constexpr-if would be a good way to go about doing this. e.g. in some header file:
// header.hpp
#pragma once
constexpr bool choice = true; // or false, if you don't want to compile some additional stuff
and in an implementation file:
#include "header.hpp"
void foo()
{
//Do some stuff
if constexpr(choice)
{
//Do some additional stuff
}
}
Note that is not a drop in replacement for #define, but it works in many cases.
A preprocessor symbol defined in one translation unit is not visible in a different translation unit. As suggested in a comment you can define it in a header and then include where needed (its not a keyword, so I chose a better name):
// defines.h
#define SOME_SYMBOL
// other.cpp
#include "defines.h
Conditional compilation via preprocessor macros has some uses, eg conditionally compiling platform specific code or excluding debug code from release builds. For anything else I would not use it, because when overused it can create a big mess and is error-prone (eg too easy to forget to include defines.h). Consider to make foo a template:
template <bool SOME_FLAG>
void foo()
{
//Do some stuff
if constexpr (SOME_FLAG) {
//Do some additional stuff
}
}
And if you still want to make use of the preprocessor, this allows you to concentrate usage of macros to a single location:
// main.cpp
#define SOME_SYMBOL
#ifdef SOME_SYMBOL
constexpr bool flag = true;
#else
constexpr bool flag = false;
int main()
{
foo<flag>();
return 0;
}
I don't know what this concept is called
Generally, pre-processing. More specifically, the pre-processor is used here to conditionally compile the program.
This a common technique that is used to create portable interfaces over platform specific ones. Sometimes it is used to enable or suppress debugging features.
I've tried it out and it doesn't work if #define is present in other file.
Macros only affect the file where they are defined.
Is there a way around this?
Define the macro in all of the files where you use it. Typically, this is achieved by including the definition from a header, or by specifying a compiler option.
And, I guess this is a C way to do things, I don't know if that would be considered as a good practice in C++, if not, what are the alternative ways?
There is no complete alternative in C++. In some cases they can be replaced or combined with templates and if constexpr.
I want to create some context-sensitive macros. The macro
#define LOG_WARNING(x) qWarning()().noquote().nospace() << x
works fine, it is located in file Macros.h. I want to define a macro, which does not print log messages when called from unit testing routine. So, I modified like
#define LOG_INFO(x) if(!UNIT_TESTING) qInfo().noquote().nospace() << x
Since in this way the macro will depend on UNIT_TESTING, I provided in the same Macros.h
extern bool UNIT_TESTING; // Whether in course of unit testing
However, the compilers tells
declaration does not declare anything [-fpermissive]
extern bool UNIT_TESTING; // Whether in course of unit testing
^
At the same time, if the external is declared in the file from which Macros.h is included, it works fine. Do I wrong something?
Here is how to share variables across source files. Nevertheless, I would highly recommend not to do so, but to implement a function (bool IS_UNIT_TESTING() ) or class which takes care of this. In this way you can change the implementation without changing the interface.
Moreover, Macros are evil. They are error prone can not be debuged easily. Use inline functions or constexp instead. The compiler will optimize it to almost the very same code.
I want to simplify things, by not creating a list of enum separately, but create the enums along the function call which creates the data where i point with those enums.
I tried to make #define which would create another #define, but it didnt work:
int defcounter = 0;
#define make_def(enumname, somedata) \
#define enumname defcounter \
defcounter++; \
func_call(somedata); \
void createstuff(){
make_def(MY_ENUM_NAME, mydata);
make_def(MY_OTHER_ENUMNAME, mydata);
}
void dostuff(){
somefunc_call(MY_ENUM_NAME);
somefunc_call(MY_OTHER_ENUMNAME);
}
But this will create error at the #define enumname:
error C2162: expected macro formal parameter
How can I make this work?
It is impossible to create new types (classes, enums, unions, whatever) at runtime in C++. One of the major features of C++ is that it is statically typed - all types must be known at compile time.
Preprocessor commands (#define, #if, #pragma, #include, ...) cannot appear in macros / defines. The problem is, that the CPP (C-Preprocessor) seperates commands by newlines, while C and C++ are unaware of newlines. In C/C++ you can write everything on one line, for preprocessor commands, you can't.
#define MY_MACRO(name) \
#define name##_macro something_cool \
enum name{ \
.... \
}
// somewhere else
void myfunc(){
MY_MACRO(myfunc_enum);
}
Now, at preprocessing time, those lines all get glued into one big line, thanks to the \ backslash:
#define MY_MACRO(name) #define name##_macro something_cool enum name{....}
Now, how would that macro look at usage?
void myfunc(){
#define name##_macro something_cool enum name{....};
}
Now, the preprocessor has to run over that #define again. But exactly what belongs to the #define, and what doesn't? For the coder it was clear when the macro was written in seperate lines, but now it isn't anymore.
What exactly is your desired output? You need to explain what you think you might get as output from the C preprocessor.
You have scope problems and an attempt to define a macro inside the replacement text of another macro.
Scope
The macro make_def() invokes an undefined function 'func_call'. The createstuff() function uses an undefined variable mydata. And function dostuff() seems to call an undefined function somefunc_call() with an enum that might, perhaps, have been defined inside a separate function.
If an enumeration is defined inside one function, that enumeration is not available to code outside that function, and specifically is not available to either called functions or calling functions. That alone limits the utility of what you seem to be attempting to do. (Yes, the enumeration values might be implicitly converted to int or some similar type, but it is not really the enumeration type that is being used.)
Defining macros in macros
You cannot create a macro that itself contains #define or any other preprocessor directive in its replacement text.
If the outer macro is invoked, the expansion does not interpret the inner #define as being a preprocessor directive, so it almost always ends up as an error, In context the # must be a stringize operator, and the word 'define' after it would have to be the name of an argument to the outer macro to have a chance of working.
// Does not work as intended
#define macro(define, prefix) #define another(name) foo(prefix ## name)
macro(something, other);
Generates:
"something" another(name) foo(othername);
The _Pragma in C99 is a partial exception to the 'a macro expansion cannot contain a preprocessor directive', but it (_Pragma) does not start with #.
Your macro is incorrect, since you cannot use a macro to create another macro, unfortunately, as the toke # has special meaning in the expansion-list: it can either quote a macro argument, or expand another macro. One easy (albeit poorly designed) way you could do this is just to use old c-style #define MY_ENUM_NAME valueas c macro do not respect scope, but this would not be good design. Another possibility is to pass in string arguments and hash on them, but all depends on what you want to do.
I'm used to this:
class Db {
_Commit(char *file, int line) {
Log("Commit called from %s:%d", file, line);
}
};
#define Commit() _Commit(__FILE__, __LINE__)
but the big problem is that I redefine the word Commit globally, and in a 400k lines application framework it's a problem. And I don't want to use a specific word like DbCommit: I dislike redundancies like db->DbCommit(), or to pass the values manually everywhere: db->Commit(__FILE__, __LINE__) is worst.
So, any advice?
So, you're looking to do logging (or something) with file & line info, and you would rather not use macros, right?
At the end of the day, it simply can't be done in C++. No matter what mechanism you chose -- be that inline functions, templates, default parameters, or something else -- if you don't use a macro, you'll simply end up with the filename & linenumber of the logging function, rather than the call point.
Use macros. This is one place where they are really not replaceable.
EDIT:
Even the C++ FAQ says that macros are sometimes the lesser of two evils.
EDIT2:
As Nathon says in the comments below, in cases where you do use macros, it's best to be explicit about it. Give your macros macro-y names, like COMMIT() rather than Commit(). This will make it clear to maintainers & debuggers that there's a macro call going on, and it should help in most cases to avoid collisions. Both good things.
Wait till C++20, you cal use source_location
https://en.cppreference.com/w/cpp/utility/source_location
You can use a combination of default parameter and preprocessor trick to pass the caller file to a functions. It is the following:
Function declaration:
static const char *db_caller_file = CALLER_FILE;
class Db {
_Commit(const char *file = db_caller_file) {
Log("Commit called from %s", file);
}
};
Declare db_caller_file variable in the class header file.
Each translation unit will have a const char *db_caller_file. It is static, so it will not interfere between translation units. (No multiple declarations).
Now the CALLER_FILE thing, it is a macro and will be generated from gcc's command line parameters. Actually if using automated Make system, where there is generic rule for source files, it is a lot easier: You can add a rule to define macro with the file's name as a value. For example:
CFLAGS= -MMD -MF $(DEPS_DIR)/$<.d -Wall -D'CALLER_FILE="$<"'
-D defines a macro, before compiling this file.
$< is Make's substitution for the name of the prerequisite for the rule, which in this case is the name of the source file. So, each translation unit will have it's own db_caller_file variable with value a string, containing file's name.
The same idea cannot be applied for the caller line, because each call in the same translation unit should have different line numbers.