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.
Related
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 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.
Good afternoon all,
I'm writing a program to read license plates that has 11 files currently:
Main.cpp
DetectPlates.h
DetectPlates.cpp
DetectChars.h
DetectChars.cpp
PossiblePlate.h
PossiblePlate.cpp
PossibleChar.h
PossibleChar.cpp
Preprocess.h
Preprocess.cpp
I have a feature allowing showing the intermediate processing steps, or not. Current this is implemented by having a global variable in Main.cpp as follows:
// global variables ///////////////////////////////////////////////////////////////////////////////
const bool blnShowSteps = false;
Then in DetectPlates.h and DetectChars.h, I have the following:
// external global variables //////////////////////////////////////////////////////////////////////
extern const bool blnShowSteps;
So in either DetectPlates.cpp or in DetectChars.cpp I can do something like the following:
if (blnShowSteps) {
cv::imshow("1a", imgGrayscaleScene);
cv::imshow("1b", imgThreshScene);
}
This is done many times in both DetectPlates.cpp and in DetectChars.cpp. So far I have used a global variable as above because I was translating this from a Visual Basic.NET version where the conditional looked at the state of a check box on a form and a global variable was an easy translation to start with.
To make this more "C++ish" I would like to change the global variable to conditional compilation. For example, in Main.cpp I would like to do:
#define SHOW_STEPS // NOTE: comment this line out, or not, to show or not show steps
Then in DetectPlates.cpp or DetectChars.cpp:
#ifdef SHOW_STEPS
cv::imshow("1a", imgGrayscaleScene);
cv::imshow("1b", imgThreshScene);
#endif
The problem is how do I implement this? If I #include "Main.cpp" in DetectPlates.h and/or DetectChars.h I get various errors depending on if I used a multiple include guard in Main.cpp or not, but either way I do not get a compile and also this violates the general practice rule of never including a .cpp file.
One possible answer seems to be adding another .h file, called "MyDefines.h" or similar, with only one line:
// MyDefines.h - single line .h file ??
#define SHOW_STEPS // NOTE: comment this line out to not show steps
But this is not an elegant solution for at least two reasons, for one adding an additional .h file to add one line seems poor, and also that would take the #define SHOW_STEPS out of the beginning of Main.cpp where it would logically be.
Another possible solution would seem to be to add a Main.h file, with the function prototypes and other stuff that is at the top of Main.cpp currently, and then to also add the #define SHOW_STEPS line. This is also not a very elegant solution either since I would be adding an entire .h file to add one line, most C++ programs do not have a Main.h file, and this would still remove #define SHOW_STEPS from being just above function main() where most people would intuitively look when figuring out the flow of the program.
Is there a way to do this where the "#define SHOW_STEPS" line would be in Main.cpp but still be seen in DetectPlates.cpp and DetectPlates.cpp?
As you suspected - place the definition in a header file (.h), and include it wherever necessary.
Either that, or don't use compiler tricks, make a configuration class, and pass the configuration object into the relevant part(s) of the program. Have the configuration class read from a file or be initialised in a relevant way.
Edit: Just to comment on, "To make this more "C++ish" I would like to change the global variable to conditional compilation". Both are pretty dodgy practises. Decent code design is probably what you're looking for!
If you introduce #defines to make your code more "C++ish", you're doing something very wrong.
You don't need to explictly remove the if's at all, the compiler can do this for you, given better circumstances. To start with, change your global variable from extern to static in a header.
...That should be enough. If in doubt, check the asm output.
Make it be defined for your whole project. Like adding -DSHOW_STEPS to GCC command line.
What is the correct strategy to limit the scope of #define labels and avoid unwarranted token collision?
In the following configuration:
Main.c
# include "Utility_1.h"
# include "Utility_2.h"
# include "Utility_3.h"
VOID Main() { ... }
Utility_1.h
# define ZERO "Zero"
# define ONE "One"
BOOL Utility_1(); // Uses- ZERO:"Zero" & ONE:"One"
Utility_2.h
# define ZERO '0'
# define ONE '1'
BOOL Utility_2(); // Uses- ZERO:'0' & ONE:'1'
Utility_3.h
const UINT ZERO = 0;
const UINT ONE = 1;
BOOL Utility_3(); // Uses- ZERO:0 & ONE:1
Note: Utility _1, Utility_2 and Utility_3 have been written independently
Error: Macro Redefinition and Token Collision
Also, Most Worrying: Compiler does not indicate what replaced what incase of token replacement
{Edit} Note: This is meant to be a generic question so please: do not propose enum or const
i.e. What to do when: I MUST USE #define & _Please comment on my proposed solution below.. __
The correct strategy would be to not use
#define ZERO '0'
#define ONE '1'
at all. If you need constant values, use, in this case, a const char instead, wrapped in a namespace.
There are two types of #define Macros:
One which are need only in a single file. Let's call them Private #defines
eg. PI 3.14 In this case:
As per the standard practice: the correct strategy is to place #define labels - in only the implementation, ie. c, files and not the header h file.
Another that are needed by multiple files: Let's call these Shared #defines
eg. EXIT_CODE 0x0BAD In this case:
Place only such common #define labels in header h file.
Additionally try to name labels uniquely with False NameSpaces or similar conventions like prefixing the label with MACRO_ eg: #define MACRO_PI 3.14 so that the probability of collision reduces
#defines don't have scope that corresponds to C++ code; you cannot limit it. They are naive textual replacement macros. Imagine asking "how do I limit the scope when I replace text with grep?"
You should avoid them whenever you possibly can, and favor instead using real C++ typing.
Proper use of macros will relieve this problem almost by itself via naming convention. If the macro is named like an object, it should be an object (and not a macro). Problem solved. If the macro is named like a function (for example a verb), it should be a function.
That applies to literal values, variables, expressions, statements... these should all not be macros. And these are the places that can bite you.
In other cases when you're using like some kind syntax helper, your macro name will almost certainly not fit the naming convention of anything else. So the problem is almost gone. But most importantly, macros that NEED to be macros are going to cause compile errors when the naming clashes.
Some options:
Use different capitalization conventions for macros vs. ordinary identifiers.
const UINT Zero = 0;
Fake a namespace by prepending a module name to the macros:
#define UTIL_ZERO '0'
#define UTIL_ONE '1'
Where available (C++), ditch macros altogether and use a real namespace:
namespace util {
const char ZERO = '0';
const char ONE = '1';
};
What is the correct strategy to limit the scope of #define and avoid unwarrented token collisions.
Avoid macros unless they are truly necessary. In C++, constant variables and inline functions can usually be used instead. They have the advantage that they are typed, and can be scoped within a namespace, class, or code block. In C, macros are needed more often, but think hard about alternatives before introducing one.
Use a naming convention that makes it clear which symbols are macros, and which are language-level identifiers. It's common to reserve ALL_CAPITALS names for the exclusive use of macros; if you do that, then macros can only collide with other macros. This also draws the eye towards the parts of the code that are more likely to harbour bugs.
Include a "pseudo-namespace" prefix on each macro name, so that macros from different libraries/modules/whatever, and macros with different purposes, are less likely to collide. So, if you're designing a dodgy library that wants to define a character constant for the digit zero, call it something like DODGY_DIGIT_ZERO. Just ZERO could mean many things, and might well clash with a zero-valued constant defined by a different dodgy library.
What is the correct strategy to limit the scope of #define and avoid unwarrented token collisions.
Some simple rules:
Keep use of preprocessor tokens down to a minimum.
Some organizations go so far as down this road and limit preprocessor symbols to #include guards only. I don't go this far, but it is a good idea to keep preprocessor symbols down to a minimum.
Use enums rather than named integer constants.
Use const static variables rather than named floating point constants.
Use inline functions rather than macro functions.
Use typedefs rather than #defined type names.
Adopt a naming convention that precludes collisions.
For example,
The names of preprocessor symbols must consist of capital letters and underscores only.
No other kinds of symbols can have a name that consists of capital letters and underscores only.
const UINT ZERO = 0; // Programmer not aware of what's inside Utility.h
First off, if the programmer isn't away of what's inside Utility.h, why did the programmer use that #include statement? Obviously that UINT came from somewhere ...
Secondly, the programmer is asking for trouble by naming a variable ZERO. Leave those all cap names for preprocessor symbols. If you follow the rules, you don't have to know what's inside Utility.h. Simply assume that Utility.h follows the rules. Make that variable's name zero.
I think you really just have to know what it is you're including. That's like trying to include windows.h and then declare a variable named WM_KEYDOWN. If you have collisions, you should either rename your variable, or (somewhat of a hack), #undef it.
C is a structured programming language. It has its limitations. That is the very reason why object oriented systems came in 1st place. In C there seems to be no other way, then to understand what your header files's variables start with _VARIABLE notation, so that there are less chances of it getting over written.
in header file
_ZERO 0
in regular file
ZERO 0
I think the correct strategy would be to place #define labels - in only the implementation, ie. c, files
Further all #define could be put separately in yet another file- say: Utility_2_Def.h
(Quite like Microsoft's WinError.h:Error code definitions for the Win32 api functions)
Overheads:
an extra file
an extra #include statement
Gains:
Abstraction: ZERO is: 0, '0' or "Zero" as to where you use it
One standard place to change all static parameters of the whole module
Utility_2.h
BOOL Utility_2();
Utility_2_Def.h
# define ZERO '0'
# define ONE '1'
Utility_2.c
# include "Utility_2.h"
# include "Utility_2_Def.h"
BOOL Utility_2()
{
...
}
We have these set of "utility" constants defined in a series of file. The problem arises from the fact that TOO MANY files include these global constant files, that, if we add a constant to one of those files and try to build, it builds the whole entire library, which takes up more than an hour.
Could anyone suggest a better way for this approach? That would be greatly appreciated.
First, if you are defining them directly in the header, I'd suggest instead delcaring them extern const, and then defining them in a cpp file:
//in .hpp:
extern const std::string foo;
//in .cpp:
const std::string foo = "FOO";
That way, at least definitions can be changed without a rebuild.
Second, examine where they are being included. If the constant file is being included in a low level header, can the include be moved to the cpp instead? Removing it might lower the coupling so it doesn't have to rebuild as much.
Third, break up that file. I'd suggest mapping out a structure you'd eventually want, start adding new constants to the new structure instead of the old file. Eventually (when you are sure you've got the structure you want), refactor the old file into the new structure, and make the old file include the entire structure. Finally, go through and remove all includes of the old file, pointing them at the appropriate new sections. That'll break up the refactoring so you don't have to do it all at once.
And fourth, you might be able to trick your compiler into not rebuilding if the header file changes. You'd have to check your compiler's documentation, and it might be unsafe, so you'd occasionally want to add full builds as well.
Do you really need every global define to be included in every file? You should probably split the constants up into categories and then split them into different files.
Every .h that is included is simply copied at that point in the file that is including it. If you change something in a file (either directly or via changing something that is included) then it absolutely needs to be recompile.
Another solution would be to have a .h file that has an accessor to a map of string name/values. Then in the .cpp file of that map/accessor you can insert the new values. Every new value you put would only need 1 file to be recompiled.
Another solution is not to include the header file anywhere. Simply extern in the variables you need in each .cpp file.
Perhaps it's time to do some refactoring to improve the cohesion and reduce the coupling in your software design. Splitting the global constant files would allow modules to be more selective about which constants need to be included, which will eliminate some of the
unnecessary coupling. In the extreme case, you could break it all the way down to one constant per file, and ensure that each module only includes the constants it needs to use.
But that could result in poor cohesion, in the sense that the constants might naturally fall into related groups, such that a module that requires one constant will generally also
require many others from that group. So the trick is to find a better grouping of constants in the various global files, then ensure that each module only includes what it needs.
(Edit: I didn't think of external constants. Indeed, my idea is kinda stupid.)
(Edit: My "stupid" macro idea actually saves build time for when constants are added. Thanks for pointing that out, Brian!)
Use parallel building :-)
Seriously, I think one solution would be to create another header called utility_ex.hpp or something where you add new constants that you occasionally merge into utility.hpp (or whatever your current utility constants header is called).
Another (less efficient) solution would be to have a macro like this:
#define constant(name) get_constant(#name)
// # means turn name into a string literal
int get_constant(const char *name);
Now suppose you want MAX_CUSTOMERS to be defined as 100. You can say:
constant(MAX_CUSTOMERS)
in the code. In get_constant's code, you might have:
int get_constant(const char *name) {
if (!strcmp(name, "MAX_CUSTOMERS"))
return 100;
//shouldn't happen
return -1;
}