I'm working on an application that includes this library, let's call Snap.h.
I found that compilation fails if Snap.h is not the last on the includes statements. And on closer look, I find this code in a header file included by Snap.h
#define Try try {
#define Catch } catch (PExcept Except){ErrNotify(Except->GetMsgStr());}
#define CatchFull } catch (PExcept Except){ErrNotify(Except->GetStr());}
#define CatchAll } catch (...){}
Basically this lets try and catch blocks to be used as statements, like so
Try;
<some code>
Catch;
You can see how this is an issue, these generic macros collide with other libraries very easily.
Unfortunately this is tens of thousands of lines of very complicated code and the application I'm working on is built around this library. Its not easily changed.
Cpp is not my strong suit, is there a way to limit the effects of macros in an include?
I not a big fan of #undef things, because you never now what other bad stuff can slumber in that big header. I prefer isolating it in a "compilation barrier" i.e. only including it in a separate wrapper translation unit, which only redefines and forwards what you need. In the following example Snap.h redefines BULLSHIT to std::terminate, but as you can try, main.cpp can use the function in Snap.h without its version of BULLSHIT:
/*! #file main.cpp
*/
#include <iostream>
#define BULLSHIT
#include "snap_wrapper.h"
int main() {
BULLSHIT
std::cout << wrapper::nice_function() << "\n";
}
/*! #file Snap.h
*/
#ifndef UNTITLED5_SNAP_H
#define UNTITLED5_SNAP_H
#define BULLSHIT std::terminate();
int nice_function() {
return 42;
}
#endif //UNTITLED5_SNAP_H
/*! #snap_wrapper.h
*/
#ifndef UNTITLED5_SNAP_WRAPPER_H
#define UNTITLED5_SNAP_WRAPPER_H
namespace wrapper{
int nice_function();
}
#endif //UNTITLED5_SNAP_WRAPPER_H
/*! #file snap_wrapper.c
*/
#include "snap_wrapper.h"
#include "Snap.h"
namespace wrapper {
int nice_function() {
return ::nice_function();
}
}
Related
I am trying once more with arduino and create a small module just to gain fluency in the cpp sintaxe.
I am trying to create a utility module with a static method and using a header constant to decide if I have to print the debug messages or not.
But even using #ifndef to avoid duplications, I did not work
In the module DataMattersUtil I set the header constant DATA_MATTERS_DEBUG to false using #ifndef to avoid duplication. But when I execute this code, the message does not print on serial monitor because the constant is always false, even setting it to true on the module DataMattersRunner.ino that is the first to execute.
File: DataMattersRunner.ino
#define DATA_MATTERS_DEBUG true
#include <DataMattersRunner.h>
DataMattersRunner runner;
void setup() {
runner.setup();
}
void loop() { }
File: DataMattersRunner.cpp
#include <DataMattersUtil.h>
void DataMattersRunner::setup() {
DataMattersUtil::debug("Running ...");
}
File: DataMattersRunner.cpp
#include <DataMattersUtil.h>
void DataMattersRunner::setup() {
DataMattersUtil::debug("Running ...");
}
File: DataMattersUtil.h
#ifndef DATA_MATTERS_DEBUG
#define DATA_MATTERS_DEBUG false
#endif
#ifndef DataMattersUtil_h
#define DataMattersUtil_h
class DataMattersUtil {
public:
static void debug(String message);
};
void DataMattersUtil::debug(String message) {
if(DATA_MATTERS_DEBUG) {
Serial.println(message);
}
}
#endif
As DataMattersUtil.h is included in multiple compilation units you have to define DATA_MATTERS_DEBUG in all of them.
Instead of adding #define DATA_MATTERS_DEBUG before all #include <DataMattersUtil.h> you would use a compiler flag to do so. For gcc and clang it would be -DDATA_MATTERS_DEBUG
Your problem is that each cpp file is handled in a different compilation unit, and you've only defined DATA_MATTERS_DEBUG to true in DataMattersRunner.ino. Because your other files are in separate compilation units, they don't see the definition in DataMattersRunner.ino.
The best solution for you is probably to provide DATA_MATTERS_DEBUG using a compiler option. I don't have Arduino experience, but with gcc you can do something like this:
g++ -c DataMattersRunner.cpp -DDATA_MATTERS_DEBUG=true
What I'm trying to do is provide a library with some defaults set by #define directives in the library header. Those would determine what functions of the library code will be compiled with a given application. In case the application developer needs to add or remove library functions, it should "override" the library's defaults with new values without modifying the library. Besides modifying the library compiled code, those application header's #define values will, in turn, add or remove parts of the application code itself. This is for an embedded system, so even small memory savings are important.
Below are the 4 test files. I can't get it working if it's even possible to do this. Maybe the right question is: What's the correct order of #define / #undef inside the project files?
library.h:
#ifndef MY_LIBRARY_H
#define MY_LIBRARY_H
#include <stdio.h>
#define FUNCTION_1 true
#define FUNCTION_2 false
class Class {
public:
Class();
~Class();
#if FUNCTION_1
void Function_1(void);
#endif
#if FUNCTION_2
void Function_2(void);
#endif
};
#endif // MY_LIBRARY_H
library.cpp:
#include "library.h"
Class::Class() { /* Constructor */ };
Class::~Class() { /* Destructor */ };
#if FUNCTION_1
void Class::Function_1(void) {
printf("Hi, this is %s running ...\n\r", __func__);
}
#endif
#if FUNCTION_2
void Class::Function_2(void) {
printf("Hi, this is %s running ...\n\r", __func__);
}
#endif
tst-09.h
#ifndef TST_09_H
#define TST_09_H
#include <library.h>
#undef FUNCTION_2 // .....................................................
#define FUNCTION_2 true // THIS IS WHERE I'M TRYING TO OVERRIDE THE LIB DEFAULTS
#endif // TST_09_H
tst-09.cpp:
#include "tst-09.h"
int main(void) {
Class object;
#if FUNCTION_1
object.Function_1();
#endif
#if FUNCTION_2
object.Function_2();
#endif
}
Take advantage of the capabilities of your linker. If you want to exclude unused or unnecessary code from you binary, one way to do that is to put each function in its own source module. (Some compiler packages support Function Level Linking, where the linker can remove unreferenced functions.)
Trying to use macros the way you show in your question would need them to be defined on the command line (and the library rebuilt with any change).
I have some code, that has namespace configurable by user as this:
#pragma once
#ifdef GRAPHICS_NAMESPACE
namespace GRAPHICS_NAMESPACE {
#endif
class Foo {
}
#ifdef GRAPHICS_NAMESPACE
}
#endif
And in cpp file, there is
#ifdef GRAPHICS_NAMESPACE
using namespace GRAPHICS_NAMESPACE;
#endif
Now I have a problem. I have defined -DGRAPHICS_NAMESPACE=Graphics and I have a header with:
#pragma once
#include "Foo.h"
class Bar {
Foo foo;
}
But Foo foo gives me error, since Foo is in namespace now named Graphics. I can solve this with adding
#ifdef GRAPHICS_NAMESPACE
using namespace GRAPHICS_NAMESPACE;
#endif
to my header, but that is not very safe since it will be using namespace everywhere where I include my header. Is there any other solution?
Although I would say this is not the optimal way to arrange things, I've seen worse and the solution to your problem is rather straightforward:
class Bar {
#ifdef GRAPHICS_NAMESPACE
GRAPHICS_NAMESPACE::
#endif
Foo foo;
}
If you insist on sticking with this design, you can clean this up, somewhat, by defining a 2nd macro:
#ifdef GRAPHICS_NAMESPACE
#define GRAPHICS_CLASS(x) GRAPHICS_NAMESPACE:: x
#else
#define GRAPHICS_CLASS(x) x
#endif
And then declare things along the lines of:
class Bar {
GRAPHICS_CLASS(Foo) foo;
}
Finally, if you insist on relying on the preprocessor for this kind of critical functionality, you may want to consider spending a little bit more time reading what your C++ book says on this topic. These are fairly basic, straightforward uses of the C++ preprocessor, which I expect should be fully explained in any introduction on what a C++ preprocessor is, and how it works.
I would do it like this:
#ifdef GRAPHICS_NAMESPACE
#define GRAPHICS GRAPHICS_NAMESPACE
#else
#define GRAPHICS
#endif
...
GRAPHICS::Foo
Imagine I have two .hpp files:
#ifndef _DEF_FILE_1_
#define _DEF_FILE_1_
inline void some_function_1(){
/*do stuff*/
}
#endif
and
#ifndef _DEF_FILE_2_
#define _DEF_FILE_2_
#ifdef _DEF_FILE_1_
inline void some_function_2(){
/*do stuff using some_function_1()*/
}
#else
inline void some_function_2(){
/*do the same stuff without using some_function_1()*/
}
#endif
#endif
My problem arises when I don't know in which order the files are included, e.g:
in the main.cpp i can have something like :
#include "file1.hpp"
#include "file2.hpp"
int main(){
some_function_2();
/*will call the function that uses some_function_1()*/
}
or
#include "file2.hpp"
#include "file1.hpp"
int main(){
some_function_2();
/*will call the function that doesn't use some_function_1()*/
}
Is there a way to make sure that as soon as both file1.hpp and file2.hpp
are included, then some_function_2() will call some_function_1()?
PS: One solution would be to include file1.hpp in file2.hpp but I can't do
that because I developp a code that may or may not depend on some library
that the end-user may or may not have.
PPS: The only other solution I can think of (even if I don't know how to
achieve this) would be to "delete" the definition of some_method_2() when
file1.hpp is included and then reinclude file2.hpp.
I believe proper solution would be to rewrite some_function_2() using SFINAE mechanism and template instead of preprocessor tricks. That way instantiation will happen in cpp file where it would be known if some_function_1() exists and order of include will not matter.
Your users should know if they have "some library" or, you should have some way of determining if that library is present. So you could do something like:
In file2.hpp
#ifndef _DEF_FILE_2_
#define _DEF_FILE_2_
#ifdef _DEF_HAS_SOME_LIBRARY_
#include "file1.hpp"
inline void some_function_2(){
/*do stuff using some_function_1()*/
}
#else
inline void some_function_2(){
/*do the same stuff without using some_function_1()*/
}
#endif
#endif
Or if possible eliminate file1.hpp entirely, and put some_function_1() in the location of #include "file1.hpp" above.
Now main.cpp should only include file2.hpp.
// optionally #define _DEF_HAS_SOME_LIBRARY_
#include "file2.hpp"
int main(){
some_function_2();
/*will call the function that uses some_function_1()*/
}
though, a solution that avoids the preprocessor would be better in my opinion.
If you don't know whether the file exists and need to handle that, well, neither c nor c++ preprocessor handle file existence checks. This is one of the reasons behind configure tools.
You need to probe for this information beforehand, and set it before compiling. There many ways to do it. Usually a tool / script, creates some configure.h header with appropriate defines is created. E.g. containing such line #define FILE1_HPP_EXISTS 1.
Then you can always rely on presence of configure.h and it will provide information you need.
If your compiler allows it you might use the _has_include macro:
Just change you file2.hpp to:
#ifndef _DEF_FILE_2_
#define _DEF_FILE_2_
#if defined(__has_include) && __has_include("file1.hpp")
# include "file1.hpp"
inline void some_function_2() {
/*do stuff using some_function_1()*/
}
#else
inline void some_function_2() {
/*do the same stuff without using some_function_1()*/
}
#endif
#endif
But keep in mind that this is a compiler specific extension.
I'm trying to write a simple parser in lex and doing it in c++. I started off by following the directions here
WIKILINK \133{2}[^\135]+\135{2}
%option noyywrap
%option c++
%{
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include <stdio.h>
#include <FlexLexer.h>
class xxFlexLexer : public yyFlexLexer
{
public:
virtual int yylex()
{
std::cout << "hello" << std::endl;
}
private:
vector<string> listOfLinks;
};
using namespace std;
%}
%%
{WIKILINK} {
int size = YYLeng();
string link(YYText());
link.erase(YYLeng()-3, 2);
link.erase(0, 2);
listOfLinks.push_back(link);
}
%%
int main()
{
ifstream in;
ofstream out;
in.open("in.txt");
out.open("out.txt");
yyFlexLexer lexer(&in, &out);
lexer.yylex();
}
When i try to compile the program lex.yy.cc, I get the following errors -
In file included from tmp.cpp:12:0:
/usr/include/FlexLexer.h:112:7: error: redefinition of ‘class yyFlexLexer’
/usr/include/FlexLexer.h:112:7: error: previous definition of ‘class yyFlexLexer’
tmp.cpp: In member function ‘virtual int yyFlexLexer::yylex()’:
tmp.cpp:33:29: error: ‘listOfLinks’ was not declared in this scope
I don't understand this error. What is happening?
Looking on the web I found this FlexLexer.h include file https://www.w3.org/2005/05/22-SPARQL-MySQL/sparql/FlexLexer.h and it appears that the signature for yylex() has an argument FLEXFIX.
virtual int yylex(FLEXFIX) = 0;
// Call yylex with new input/output sources.
int yylex(FLEXFIX, istream* new_in, ostream* new_out = 0 )
{
switch_streams( new_in, new_out );
return yylex(FLEXFIX2);
}
However other versions of the file such as https://www.w3.org/2008/04/SPARQLfed/win/FlexLexer.h do not.
virtual int yylex() = 0;
// Call yylex with new input/output sources.
int yylex( FLEX_STD istream* new_in, FLEX_STD ostream* new_out = 0 )
{
switch_streams( new_in, new_out );
return yylex();
}
By the way your yylex() function is not returning an int value.
See also #Gir comment with a link to a bug report Bug 67277 - Error compiling libclassparser_la.all_cc.cc: "class yyFlexLexer" redefined.
The problem is that the FlexLexer.h header has a strange way of
handling multiple inclusions of itself. tokenizer.l (tokenizer.cc)
and ClassParser.cc both include this header indirectly, and in
separate compilation they work fine; but when compiling concatenated
source, a "#define yyFlexLexer yyFlexLexer" declaration (inserted by
flex) carries through from tokenizer.cc to ClassParser.cc, and causes
havoc on the second inclusion. (In the error message quoted above, the
two FlexLexer.h lines are the second and first inclusions,
respectively.)
The/A solution is to "#undef yyFlexLexer" at the end of tokenizer.l,
and I will attach a patch that does this with an explanation why.
The comments in the FlexLexer.h include file mention using what is in the bug report for multiple instances and includes. Not sure why it would be needed in something this straightforward and simple though.
// This file defines FlexLexer, an abstract class which specifies the
// external interface provided to flex C++ lexer objects, and yyFlexLexer,
// which defines a particular lexer class.
//
// If you want to create multiple lexer classes, you use the -P flag
// to rename each yyFlexLexer to some other xxFlexLexer. You then
// include <FlexLexer.h> in your other sources once per lexer class:
//
// #undef yyFlexLexer
// #define yyFlexLexer xxFlexLexer
// #include <FlexLexer.h>
//
// #undef yyFlexLexer
// #define yyFlexLexer zzFlexLexer
// #include <FlexLexer.h>
// ...
Looking at the link you provided, I wonder if you need to remove the FlexLexer.h include since you have only the one parser.