To speed up the compiling process, I'm trying to simplify my header file MyClass.hpp by forward-declaring STL containers such as std::vector, std::set...
But std::set can NOT be forward-declared within following codes, while std::vector can be.
namespace std {
template<typename T, typename A> class vector;
template<typename T, typename C, typename A> class set;
};
class MyClass_t {
void showVector( std::vector<int>& );
void showSet( std::set<int>& );
}
As we know, the header <set> is very long and complicated. If we add #include <set> into MyClass.hpp, in fact every translation units that uses MyClass_t have to include implicitly the header <set>. But I think that it's not necessary, because not every translation units using MyClass_t will call MyClass_t::showSet, so I think the simplification makes sense.
How to do it?
One of the purposes of namespaces is to separate code that comes from different sources. This is often thought of avoiding name conflicts, but it goes to a deeper level.
When a library defines a namespace, it (typically) claims total possession of it. The library reserves the right to change any and all aspects of everything defined in the namespace, usually guaranteeing only the public API. This extends to forward declarations. Any forward declarations in the namespace are the library's domain unless stated otherwise, as the library may want to change things behind the scenes. Some libraries take this seriously and provide forward-declaration headers, but without those, you are out of luck.
In general, do not expect to be able to forward declare anything you do not control. Even if it works initially, it is liable to break at any upgrade/patch to the library.
Moving on to std::set, the std namespace is reserved for the standard library. The standard library grants you the ability to declare a few things in the std namespace in restricted circumstances, but otherwise it is off-limits to you. Unfortunately for your goal, the standard library does not require forward-declaration headers. If you want your code to be cross-platform and/or stable after a compiler upgrade, you will need to include the full header.
Going on a tangent: this is the basis for specifying that adding your own definitions to namespace std is undefined behavior. It's not that such things are guaranteed to break something, but that the language standard cannot guarantee what exactly will break things. (Realistically, if you were to define a class named supercalifragilisticiwillmisspellthis in namespace std, probably nothing will blow up.) To keep things simple, the "undefined behavior" label is applied and implementations are given maximum freedom.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With