C ++ removing #include <vector> or #include <string> in class header
I want to remove, if possible, inclusions like <vector> and <string> from my class header file. Both string and vector are return types of functions declared in the header file.
I was hoping I could do something like:
namespace std { template <class T> class vector; } And, declare the vector in the header and include it in the source file.
Are there any reference situations in which you must include the header, and situations in which you can pull included in the source file?
You cannot safely redirect STL template declarations, at least if you want to do this portable and securely. The standard clearly states the minimum requirements for each STL element, but it leaves room for extension extensions that can add additional template parameters if they have default values. That is: the standard states that std :: vector is a template that accepts at least 2 parameters (type and allocator), but can have any number of additional arguments in a standard compatible implementation.
What is the point of not including line and vector headers? Of course, the one who was going to use your class should have included it, since it is on your interface.
When you ask for a link to decide when to include and when to forward the announcement, my advice would be: to include everything that is part of your interface, forward the declaration of internal details.
There are more problems here than simple compilation performance. If you click the include type, which is located in your public (or secure) interface outside the header, you will create dependencies on the order of inclusions. Users should be aware that they must include the string before including the header, so you give them one more thing to worry about.
What things should be included in the implementation file: implementation details, registrars, elements that do not affect the interface (database connectors, file headers), internal implementation details (that is, using STL algorithms for your implementation does not affect your interface, functors, created for a simple purpose, utility ...)
Standard containers often have additional default template parameters (dispensers, etc.), so this will not work. For example, here is a snippet from the GNU implementation:
template<typename _Tp, typename _Alloc = std::allocator<_Tp> > class vector : protected _Vector_base<_Tp, _Alloc> { ... }; This was what I tried to do before, but this is not possible due to the patterns.
See my question: Forwarding a base class declaration
Since such headings do not change during your development, it is not worth optimizing, anyway ...
There is no simple obvious way to do this (as others have explained it very well).
However, these headers should be considered as part of the language (really!), So you can easily resolve them to your own headers, no one will complain.
If your problem is related to compilation speed, I recommend that you use a precompiled header and put these std headers (among other things) in it. This will significantly increase compilation speed.
Sorry for the answer "the real winner is the one who avoids the fight."
If the string and vector are used only in signatures of non-public members of your class, you can use the PImpl idioms:
// MyClass.h class MyClassImpl; class MyClass{ public: MyClass(); void MyMethod(); private: MyClassImpl* m_impl; }; // MyClassImpl.h #include <vector> #include <string> #include <MyClass.h> class MyClassImpl{ public: MyClassImpl(); void MyMethod(); protected: std::vector<std::string> StdMethod(); }; // MyClass.cpp #include <MyClass.h> #include <MyClassImpl.h> void MyClass::MyMethod(){ m_impl->MyMethod(); } You always include a vector and a string in the header file, but only as part of the implementation of your class; files, including only MyClass.h, will not pull the string and vector.
Just include the header in any file where you reference the STL collection.
As already mentioned, there is no way to reliably promote STL class declarations, and even if you find them for your specific implementation, it will probably break if you use a different STL implementation.
If compilation units do not instantiate classes, this will not make your object files anymore.
Attention
Expect this to cause noise.
The language allows you to create your own classes:
// MyKludges.h #include <vector> #include <string> class KludgeIntVector : public std::vector<int> { // ... }; class KludgeDoubleVector : public std::vector<double> { // ... }; class KludgeString : public std::string { // ... }; Modify your functions to return KludgeString and KludgeIntVector. Since these templates are no longer templates, you can forward them to your header files and include MyKludges.h in your implementation files.
Strictly speaking, derived classes do not inherit base class constructors, destructors, assignment operators, and friends. You will need to provide (trivial) implementations of whatever you use.
// LotsOfFunctions.h // Look, no includes! All forward declared! class KludgeString; // 10,000 functions that use neither strings nor vectors // ... void someFunction(KludgeString &); // ... // Another 10,000 functions that use neither strings nor vectors // someFunction.cpp // Implement someFunction in its own compilation unit // <string> and <vector> arrive on the next line #include "MyKludges.h" #include "LotsOfFunctions.h" void someFunction(KludgeString &k) { k.clear(); } With the exception of adding overloads to std::swap (the only exception I can think of right now), you are usually not allowed to add anything to the std . Even if it was allowed, the actual declaration for std::vector much more complicated than the code in the OP. See Nikolai N. Fetisov's answer for an example.
All aside, you have an additional problem that your class users will do with functions that return std::vector or std::string . C ++ Standard section 3.10 says that functions that return such objects return r values, and r values must be of full type. In English, if your users want to do anything with these functions, they will need to #include <vector> or <string > in any case. I think it would be easier to #include header for them in your .h file and do with it.
I assume your goal is to speed up compilation time? Otherwise, I'm not sure why you would like to remove them.
Another approach (not very, but practical) is to use macrographs around include itself.
eg.
#ifndef STDLIB_STRING #include <string> #define STDLIB_STRING #endif Although this looks messy, on large codebases it does increase compilation time. We created a Visual Studio macro that will automatically create security features. We bind the macro to a key for easy coding. Then it just becomes the company’s coding standard (or habit).
We also do this for our own inclusions.
eg.
#ifndef UTILITY_DATE_TIME_H #include "Utility/DateTime.h" #endif Since we have Visual Studio helpers to automatically generate guards when creating our own header files, we do not need #define. The macro knows that this is an internal inclusion because we always use
#include ""
for our own includes and
#include <>
for external includes.
I know that this does not look very nice, but it accelerated our compilation times on a rather large code base by more than half an hour (from memory).