C++ has namespaces to prevent collisions of things with the same name.
Header guards serve a different purpose. They prevent include
ing the same header twice. However, they can suffer from the same problem: what if two header guards from different files use the same popular name? What if there are two libraries that have a LinkedList
class:
#ifndef LinkedList_H
#define LinkedList_H
// stuff
#endif
Why are those two means to uniquely identify code so different?
It’s like one sophisticated language feature on one side and some macro contraption with an arbitrary string on the other.
Why are naming conflicts not a problem for header guards? Shouldn’t the namespace be part of the header guard, to make it as unique as the namespace, so that it not only prevents duplicated include
but also naming conflicts?
1
One method I use is to build a more complex macro name that has a practically zero chance of colliding with other names. This could be built from the following components:
- Project name
- Namespace name
- File name
- Random number or GUID
Example:
#if !defined MYPROJECT_MYNAMESPACE_FOO_HPP_9E72F091C4A833D7
#define ...
Overkill? Yes. Easy to do? Yes. Has such an infinitesimally small chance of a collision that I can write and forget about it? Yes.
2
Header guards are not as sophisticated as namespaces because they are part of the preprocessor (like headers themselves), and the preprocessor is an extremely primitive part of C++, inherited from C.
A common convention is to add a project and in-project path as a prefix, e.g.
#ifndef MYPROJECT_UTILITY_CONTAINERS_LINKED_LIST_HPP
#define MYPROJECT_UTILITY_CONTAINERS_LINKED_LIST_HPP
It’s not the only one of course.
#pragma once
Really, it supported by all major compillers (preprocessors). Some projects moves to use it: Qt Creator for example. Yes, it is non-standard.