The correct way to deal with this is to setup your build environment in a way that name clashes become less likely.
Guidelines for writing libraries
For example, most third party libraries do not introduce plain files to the compiler's include path. Instead they introduce a directory that contains the files. You can increase flexibility by introducing subdirectories for different modules.
Consider the directory structure of Boost. On the top-level, Boost only introduces a single name to the include search path: The boost
directory. That way, even though boost
introduces a number of header filenames which are likely to clash (like array.hpp
, thread.hpp
, or function.hpp
), they are all wrapped away in the subdirectory:
#include <boost/thread.hpp> // this is boost's header
#include "thread.hpp" // some header specific to my current project
// no name clash :)
The same concept is used for the different libraries that ship with Boost. For example, both Boost lockfree and Boost assign have a queue.hpp
header. But they live in different subdirectories, so there is no clash:
#include <boost/lockfree/queue.hpp>
#include <boost/assign/std/queue.hpp> // no clash :)
To make finding the right header file easy, Boost uses the same structure for include files and namespaces: The lockfree queue lives in boost::lockfree
namespace, while the functions from the assign queue header go to boost::assign
. That way it is not only straightforward to find the matching namespace from an include file and vice versa, it also decreases the likelihood of namespace clashes, as a namespace clash is also likely to manifest in a physical name clash on the file layer.
You can adapt these guidelines for your own project
- Don't introduce bare include files directly to the include path. Instead group them together in a directory to avoid polluting the include path with names.
- Use directory trees to further structure the include files of modules inside a single library.
- Try to match the physical structure with the logical structure. Filesystem include paths should resemble namespace hierarchies if possible.
This avoids most of the nameclashes in the first place. The question is what if you have to use a third-party libraries that do not follow these rules and you get a clash that is outside your control?
Guidelines for dealing with name clashes by third-party libraries
The answer is to be brutal and enforce the separation through the build environment. Reorganize the include paths by moving conflicting libraries into uniquely identifiable subdirectories to resolve physical conflicts. This is usually non-critical. Logical conflicts require patching and recompiling, which is a lot more inconvenient. But if you really run into name clashes here, it is a sure indication that at least one of the library vendors did not do their job too well and you should consider filing a bug.
Stay away from ad-hoc fixes like #include_next
to fix physical clashes or preprocessor defines to fix logical clashes. They are dirty hacks and while they might solve your problem temporarily, they are very likely to come back and bite you eventually.