'Which type of #include ("" or <>) when writing a library in C/C++

I am writing a library in C++. The library has multiple headers and cpp files and needs to be cross platform (Windows Visual Studio and Linux gcc). When built the library and headers are installed in a system directory somewhere, where they can be found by other code on the same machine (e.g. /usr/local on a Linux system).

If one of my headers needs to #include one of my other headers then should I use angle brackets or quotes?

I feel like angle brackets is what should be used once the library is installed so that system directories are checked, but when building the library I need to use quotes so that local directories are checked and I don't pick up an out of date version from the system directories.

I am aware ow what the different versions of #include <filename> and #include “filename” mean. I am asking which is appropriate and why, for the situation of writing a library.



Solution 1:[1]

When you use angle brackets, the compiler searches for the file in the include path list. When you use double quotes, it first searches the current directory (i.e. the directory where the module being compiled is) and only then it'll search the include path list.

So, by convention, you use the angle brackets for standard includes and the double quotes for everything else. This ensures that in the (not recommended) case in which you have a local header with the same name as a standard header, the right one will be chosen in each case.

Refer following SO answer for more details

Difference between angle bracket < > and double quotes " " while including header files in C++?

Solution 2:[2]

If you use "..." the compiler will search the local directory first and then the system directory.

If you use <...> the compiler will search the system directory.

A user library will normally reside along with the program. So you can use "..."

You can in any case add additional search paths using the IDE or make file.

Solution 3:[3]

if the headers in the your working directory, you should use "" but, if the headers in the system path or inside the your include path you should use <>.

Solution 4:[4]

I'm currently facing the same decision with a library I'm working on, which is intended to be consumed by projects other than my own. None of the other answers here address the practicality of quoted vs angular form of includes within libraries themselves, but merely explain the technical differences between the two forms.

There seems to be a divide into which include form is best for library sources/headers including headers from the same library. I don't think I'm qualified to give the Ultimate Answer. What I'm going to do here instead is attempt to summarize the pros and cons of each approach as best as I can, and link to some resources I found online.

The C++ Core Guidelines [1] has this to say under SF.12:

Library creators should put their headers in a folder and have clients include those files using the relative path #include <some_library/common.h>

The advantages of the angular form listed below assume that a library's headers are put into such a "root" folder named after the library (I hate it when libraries don't do that).

Unfortunately, the C++ Core Guidelines do not explicitly state what library creators should do when including their own headers from within their own library source/header files. However, a contributor kindly clarified to me in [4] that in their example:

#include "foo_utils/utils.h"
    // A file locally relative to foo.cpp in the same project, use the "" form

the term project also applies to libraries. That contributor also clarified that "locally relative" was left up to the reader so that instances of #include "../../include/somelib/foo.hpp" could be interpreted as non-locally relative so that #include <somelib/foo.hpp> may be used instead.

Note that the C++ Core Guidelines, co-authored by Stroustrup, somewhat contradicts the AV Rule 33 of Stroutrup's earlier JSF coding standards [2] when it comes to the preferred #include form. Perhaps he changed his views regarding this.

Advantages of the #include <somelib/foo.hpp> approach:

  • As discussed in [3], it allows the user to supply their own patched library header files by putting them in a directory that's searched earlier, via -I or -isystem compiler flags. Patching via this method is probably only viable for header-only libraries.
  • If one of your library's headers is named the same as one of the system's headers, then it's less confusing which one you're referring to. e.g.: #include <somelib/float.h> vs #include "float.h", where float.h happens to be a C standard library header.
  • Avoids relying on the inconsistent behavior of the quoted form among compilers, and conforms to AV Rule 33 of Stroutrup's JSF coding standards [2]. This may not be a problem if the library is not aiming to be portable across many compilers.
  • It avoids ugliness when the included file lives in a parent or sibling directory of the including file. E.g. #include <somelib/foo/bar.hpp> vs #include "../foo/bar.hpp". Also consider the case where the source and header files live in different directories of the library project: #include <somelib/foo/bar.hpp> vs #include "../include/foo/bar.hpp" when including from a library cpp file.
  • When used in the library's cpp files, it allows the user to simply embed the library's cpp files into the application's build system, and not have to maintain the same relative directory structure between the library's source and header files. This may be desirable if the library consists of only one (or a few) cpp files, and the application project doesn't want to use the build method provided by the library. For example, an application project uses bazel, but the library only provides a CMake build.

Advantages of the #include "foo.hpp" approach:

  • Makes it clear to the reader that the file to be included is part of the same "project" as the including file.
  • If a user has both locally-installed and system-installed versions of the library, it can avoid the system-installed header being accidentally included if the user neglected to set the proper -I or -isystem flags.
  • If a beginner user doesn't know how to set up -I or -isystem flags properly to point to a local version of the library, they can just do #include "../dependencies/somelib/include/somelib/foo.hpp" (which I find terribly ugly - perhaps irrationally).

Based on the above research and on the kind help from the C++ Core Guidelines contributor, I'm now personally aiming to adopt the following convention:

  • When a library header file includes another header of the same library: Use #include "foo.h", #include "bar/foo.hpp", or #include "../bar/foo.hpp", depending on the relative location of the other header file.
  • When a library source (cpp) file includes one of the library's own headers: Use #include <somelib/foo.hpp> or #include <somelib/bar/foo.hpp>.

The former makes it clear that I want to include a header file that's bundled with the same library as the file doing the including.

The latter makes it possible for the library source files to be compiled by being directly dropped into an application's build system, without having to maintain the same relative directory structure between the library's source and header files. It also avoids the #include "../include/somelib/foo.hpp" ugliness in favor of the cleaner #include <somelib/foo.hpp>.

When my library source files are being compiled using the library's CMake scripts (to generate a static/shared library), the CMake scripts are in control of the -I and -isystem flags and can thus ensure that the correct library headers path will be given top search priority.


[1] https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rs-incform

[2] https://www.stroustrup.com/JSF-AV-rules.pdf

[3] https://lists.boost.org/Archives/boost//2008/09/142030.php

[4] https://github.com/isocpp/CppCoreGuidelines/pull/1596#issuecomment-1113901271

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Rizwan
Solution 2 Rishikesh Raje
Solution 3 erenbasturk
Solution 4