How to include part of file by C++ preprocessor #include - c++

I want to refer some stable library code which is not maintained by me. Actually it is some MFC code snippet.
But, whenever I want to include the code snippet, I have to #include entire file, which consequently I have to include other stuff, then the whole MFC ... The consequence is not acceptable.
Currently, I copy/paste the code snippet into my project, but I feel disgraceful. Can I just refer part of a file by C++ preprocessor?
Even the code is hard-linked with specific MFC version, it is better than duplicate them in my project. With such hard-link, I will know it's from MFC and save my time to check them.
Is there some super #include usage?
Can we write something like
#include "foo.h" line [12, 55)
which means to include line 22 to 54 for foo.h

What some have done is write #ifdef-sections in their headers to allow including files to only get specific parts. I don't know if your MFC file has those but you can look through it and use any existing ones or write your own.
The header usually look something like this
#ifdef USE_FANCYPANTS
bool hasFancyPants();
#endif
#ifdef USE_COOLSTUFF
void doCoolStuff();
#endif
And your include files then use #define before including.
#define USE_FANCYPANTS
#include "header.hpp"
Then you only get hasFancyPants() and not doCoolStuff()

You can use conditional compilation to inlcude/exclude stuff you dont need. You have to change the source code slighty, and amend project settings.
Can use typedef keyword, which would define types differently for MFC and non-MFC, and/or specific to your project settings, and the legacy code.
You may put entire stuff in a DLL or a .LIB (having code, not just declaration), and put the linker pragma in header file itself.

Related

Make a version file of macros which run at compile time

I want to ask if I can make a file of macros that basically defined at compile time and use these macros in my c++ code which compiles specific code if the condition is true. SO what is basically the extension for that file is it a .txt file or a .h file. and how to put this file in CmakeList.txt to make it executable at compile time. for example like this in a specific file?
#define melodic 1
#define noetic 2
A C++ macro is a shortcut for writing code, what happens when you compile your project is that this code:
#define SOMETHING 32
int i = SOMETHING
Is changed to before it is compiled:
int i = 32
So a macro just substitutes text wherever you place it. There is also another use of macros that maybe is what you are looking for. You can use the preprocessing directive #ifdef MACRO to compile some code conditionally. For example, let's say that you have a function that is only there for debugging, but you don't want that code to make it to release. You could define it like:
void hello() {
#ifdef DEBUG
print("debug");
#endif
}
Then, if that file has a #define DEBUG before the #ifdef macro, the code will be included. Otherwise, the code will be discarded. Note that to use #ifdef the macro body may be empty or not, it just checks if the defined directive was used.
What you might want to accomplish is to have a series of preprocessor macros that you either set or don't in a separate configuration file to change the code produced. They are a very powerful tool, but they must be use with caution since having too many can make code not very readable.
To accomplish that, you need to include the #define MACRO in the same file that you are checking if it is defined, and before you check it. If you are only using that macro in that file, it would be good to place it at the top of it, but if you use it on multiple files you can create a header file (.h) and use #include "name.h", since include copies the contents of the header file there, therefore adding the macro definitions to your file.
The preprocessor directives are dependent on the compiler, so the version and type of compiler you use (gcc, clang...) will have different support for them. However, defined and ifdef are very widely spread and most if not all compilers have them. I recommend reading more about directives, for example here.
Finally, in case you go the route of the .h file, you would add it like any other header file you have in your project to the CmakeList.txt.

Preventing multiple #define when including headers

coming from python and am a bit tripped up on what the proper approach to this is.
I am trying to include this library in my project:
https://github.com/nothings/stb/blob/master/stb_image.h
to do so, i have to #define STB_IMAGE_IMPLEMENTATION exactly once before importing the file (as per that file's doc)
This makes sense, where I am confused is, I have CLASS.h/cpp and in .h I define functions that use typedefs from that file, so I have
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>
in that header file, and can't move these lines to .cpp as headers needs the defs for function def, but as soon as another file includes this header, (#ifndef wont help, i believe), that will be defined twice
I have a structure where TOP creates the CLASS above, but parent also creates OTHER, and OTHER needs to include PARENT, which includes CLASS, which triggers the issue (and prevents me from just moving the #define to PARENT) Note the actual class structure is more complex then this, but this idea seems to be a core issue, and I'm looking for the general best practice.
So, is there some way to ensure these #defines are defined before anything else, and done only once? This seems like a fundamental thing but I can't figure it out - What's the best approach?
This code is a library, and doesn't have a defined entry if that matters
Create a cpp file (or whatever extension you are using for your source files) whose sole purpose is to have
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>
and don't forget to include this cpp file into your project so that it is compiled and the result is linked into your program. In all other places where you need something from this library, just include the stb_image.h header as usual.
These "implementation" macros are a "trick" used by some library authors to make "installing" their library easy. The idea is that when a specific macro (chosen by the library authors) is defined before the header of that library is included, some code with the actual implementation will be added. That is why this must be in a source file instead of a header and only in one source file (otherwise you get multiple definitions for the same functions).
You should have the #define STB_IMAGE_IMPLEMENTATION macro definition in exactly one source file that includes <stb_image.h> (a .cpp file, not in a header).
Since you can also only have one source file that defines main(), it is simple to put the #define in the same file as main() (as long as it also includes <stb_image.h>), but it can be used in any other source file if you prefer. You could even create a source file stb_image_imp.cpp that contains just the two lines shown, and link that into your program (or library) too.
All other source files in the project should only include <stb_image.h> without also defining the macro.
#define is a preprocessor directive and doesn't actually get run everytime the header is accessed so you should
't have any problems
if you are using visual studio you can also do #pragma once to only parse the file once stopping anything from happening twice

C++ preprocessor executing both #ifdef and #ifndef

So I'm currently working on something that uses OpenCL. The OpenCL spec provides the users with a directive which must be included before the inclusion of the header (cl.h)
#define CL_TARGET_OPENCL_VERSION 110
Which basically defines the version they want to use. Suppose I'm making a library and I want my users to define this instead of me defining this inside my files. What I did was.
-----main.cpp---
#define CL_TARGET_OPENCL_VERSION 110
#include "library.h"
-------x---------
----library.h-----
#ifdef CL_TARGET_OPENCL_VERSION
#pragma message("def")
#endif
#ifndef CL_TARGET_OPENCL_VERSION
#pragma message("ndef")
#endif
.... include other headers.
--------x---------
And the compiler prints both def and ndef messages. And the OpenCL library also throws a warning that it's undefined. I thought that the library header would get substituted into main and it'd only print the def message. Is there anything I understood wrong?
I'm particularly confused as to where does the preprocessor start? If it starts from main.cpp and goes from top to down, then it surely has defined the macro. After that it sees the library inclusion, then it should only print the def message but it prints both.
This leds me to believe the preprocessor does scan the header file before including it in main? Dunno the reason why. Also I have assured that the library header isn't included elsewhere.
One interesting thing I noticed was, if i did this
-----helper.h---
#define CL_TARGET_OPENCL_VERSION 110
-------x---------
----library.h-----
#include helper.h
#ifdef CL_TARGET_OPENCL_VERSION
#pragma message("def")
#endif
#ifndef CL_TARGET_OPENCL_VERSION
#pragma message("ndef")
#endif
.... include other headers.
--------x---------
It prints the def message "twice". If anybody can explain all this I'd be grateful.
EDIT:- The files I'm compiling are main.cpp library.h and library.cpp
Library.cpp includes library.h from the start as usual. Maybe this other cpp is causing the problem?
In C/C++ programs, the compiler handles each .c and .cpp file separately.
The compilers build each source file (NOT the header files, only .c and .cpp files) independently from each other (this source files are called compilation unit).
Thus, when your main.cpp is built, the compiler finds the #define CL_TARGET_OPENCL_VERSION 110 you have added on top of the main.cpp file, emiting the defmessage.
But when the compiler builds the library.cpp file, it does not find the version define, so it emits the ndef message.
So, following this explanation, it is completely normal that in your last case, when you add the define to the .h file, the compiler emits the def message twice, once for the main.cpp file and once for the library.cpp file.
Now, the problem is where should you add the define, in order to have the program built consistently, with the same version for all the .cpp files.
Usually, all the IDEs have some configuration page where you can add global defines, for all the project, which are "inserted" into all the compilation units before everything else. So when the IDE calls the compiler, it passes the same defines to all the compilation units. You should add this kind of defines in this page.
In your IDE (I am using Code::Blocks, v 17.12), you can find this page in the menu: Project / Build Options
For each type (Debug or Release), you have to go to the tab Compiler Settings, and there to the sub tab #defines. There you can add global defines, which can be different if you are building in Debug or in Release mode (of course, if you set the same in both modes, they would be the same).
Once you have added your define here, please, remove it from the main.cpp, library.h and any other place where you may have added it, in order to avoid duplicities.
From the comments about portability:
You have several options:
Always use Code::Blocks: this would be the easiest way, since you can pass the Code::Blocks project along with the source files, and everything would be already setup.
Use cmake, which is a script build system, where you can set defines and so in the same way as using an IDE. cmake is much widely used than Code::Blocks, so maybe it is a better option.
Add a new options.h header file, where you set all the defines, and include it to all your .c/.cpp. This setup has the additional benefit that for different systems, changing only the options.h file the build can be completely different. This is a manually setup of what the IDE is doing. It has the advantage that does not rely on external tools, but the disadvantage that you have to remember to add it in all the new .cpp files added to the project.
My recommendation is go with cmake, just as the others have said.
Prefer using #ifndef XXXX_h #define XXXX_h #endif over #pragma once
If your #include search path is sufficiently complicated, the compiler may be unable to tell the difference between two headers with the same basename (e.g. a/foo.h and b/foo.h), so a #pragma once in one of them will suppress both. It may also be unable to tell that two different relative includes (e.g. #include "foo.h" and #include "../a/foo.h" refer to the same file, so #pragma once will fail to suppress a redundant include when it should have.
This also affects the compiler's ability to avoid rereading files with #ifndef guards, but that is just an optimization. With #ifndef guards, the compiler can safely read any file it isn't sure it has seen already; if it's wrong, it just has to do some extra work. As long as no two headers define the same guard macro, the code will compile as expected. And if two headers do define the same guard macro, the programmer can go in and change one of them.
#pragma once has no such safety net -- if the compiler is wrong about the identity of a header file, either way, the program will fail to compile. If you hit this bug, your only options are to stop using #pragma once, or to rename one of the headers. The names of headers are part of your API contract, so renaming is probably not an option.
(The short version of why this is problematic to use #pragma is that neither the Unix nor the Windows filesystem API offer any mechanism that guarantees to tell you whether two absolute pathnames refer to the same file.)

C++ Don't include includes from previous header

Say I have the following:
Main.cpp
#include <Windows.h>
#include "B.h"
...
-
B.h
...
SomePrototypeFunctionNeedingWindowsH();
-
In B.h, I'm not required to include Windows.h again as it's already been included beforehand. For clarity, I would like to be required to include Windows.h for each new file that wants it. I'm using VS2015.
Can this be done?
Can this be done without impact on compilation time?
Would this be considered an acceptable practice?
Will I run in to any issues if this was done?
Maybe you're looking for the preprocessor directives in C++.
They are something like:
#ifndef HEADERFILE_H
#define HEADERFILE_H
/*Your header declarations/definitions*/
#endif
In this preprocessor technique, you basically tell your compiler that it should not include the same header for multiple times.
Refer to this post for more thorough understanding
Compile each .h file into throw-away test output .objs. This can be done manually, or through a script to run on whatever project management system you use.
Naturally something has to add the .h files to the project management system.
A .h file that can be compiled as a source file includes all the header files it needs.
The exact steps -- you could iterate through each .h inmthe directory tree, output a .h.cpp file, add that .h.cpp file to a project that you do not otherwise use, and build that project.
What language ypu write this in depends on what scripting languages you are good at.

how to prohibit other developers to #include a third party header in C++

So there is third-party library that has a header file you need to include in order to use it. Since the implementation of the library is not object oriented I wrote a Class to encapsulate all usage of the library, so in case it needs to be replaced I can just modify the implementation of that class.
Since other developers will be working in the same code base I want a way to give them an error if they include the library. This is to avoid having references all over the place to the library.
For example if they do something like this:
#include "cool_library.h"
they get an error saying:
do not include directly cool_library.h, instead use the cool_library_wrapper class
is this possible? I'm using GNU GCC
Since you're using gcc, you can use the #include_next feature of the preprocessor: Create a header with the same name as the 3rd party's in a directory that will have higher precedence when looking for header files. In your version of the header use something like
#if WRAPPER_HEADER_HAS_BEEN_INCLUDED
# include_next <cool_library.h>
#else
# error ...
#endif
You could use a #error preprocessor directive within a #ifndef block.
For example in the orginal .h file have this:
#ifndef COOL_LIBRARY_WRAPPER_CLASS_INCLUDED
#error "do not include this file directly
#endif
And in the wrapper class's header file do this:
#define COOL_LIBRARY_WRAPPER_CLASS_INCLUDED
This would only be possible if you're okay with modifying the cool_library.h file. You could do something like:
cool_library.h
#ifndef INCLUDED_FROM_COOL_LIBRARY_WRAPPER
#error do not include directly cool_library.h, instead use the cool_library_wrapper class
#endif
.. remainder of original cool_library.h
cool_library_wrapper.h
#define INCLUDED_FROM_COOL_LIBRARY_WRAPPER
#include "cool_library.h"
... your wrapper
#undef INCLUDED_FROM_COOL_LIBRARY_WRAPPER
Of course, you still can't prevent your coworkers from defining INCLUDED_FROM_COOL_LIBRARY_WRAPPER themselves and including the original header file. This is a social problem that does not have a technical solution.
If you usually include some project-wide headers you could check for the presence of the include guard from the third-party header, e.g.
// third_party.h
#ifndef THIRD_PARTY_H
#define THIRD_PARTY_H
...
and
// your_project_wide.h
...
#ifdef THIRD_PARTY_H
#warning "Please include "cool_library.h"
#endif
...
Caveats here: #warning is a gcc extension, and all this relies on the external dependencies being included before your project headers (which you might not want to do).
Don't put <cool_library.h> in the normal build include path. You can either use special CFLAGS for your wrapper to give it access or access it with a more explicit path like <vendor/xyz/cool_library.h> from some higher-level include path.
Another path-based approach would be to put a local <cool_library.h> earlier in the include path and use the #ifdef/#error approach above. If the magic define is present then the stub header can use the more explicit path to pick up the real header. (Some compilers have a hack to continue the search path if you include something named exactly the same thing as the header that's being read)