It could happen that two independent libraries have two identical file names.
The following example is like that.
The file names C.cpp and C.h appear in both libraries.
I would think that the compiler could figure out that they are distinct files because the paths are different.
But compiling gets this error on line 8:
error: 'lib2' has not been declared
Users don't always have the luxury of editing a library.
What is the usual way to make this compile if the user can not edit the library?
main.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14
#include <C.h> //this gets error
//#include "lib2/C.h" //this works
#include <D.h> //this works
int main()
{
lib2::C2 c; //error: 'lib2' has not been declared
c.fn1();
c.fn2();
lib1::D d;
d.fn3();
}
lib1/C.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14
#ifndef lib1_C_h
#define lib1_C_h
#include <iostream>
namespace lib1
{
class C
{
public:
virtualvoid fn1();
};
}
#endif
C:\Users\wolf\Documents\lib_namespace>make
g++ -Wall -Ilib1 -Ilib2 -c main.cpp -o obj/main.o
main.cpp: In function 'int main()':
main.cpp:12:2: error: 'lib2' has not been declared
lib2::C2 c; //error: 'lib2' has not been declared
^
main.cpp:12:11: error: expected ';' before 'c'
lib2::C2 c; //error: 'lib2' has not been declared
^
main.cpp:13:2: error: 'c' was not declared in this scope
c.fn1();
^
make: *** [obj/main.o] Error 1
Well yeah, the compiler is going to give you an error because line 2 is commented out. Therefore the compiler has not seen the lib2 namespace.
Whether or not the compiler can figure out the files are different depends whether or not the include names are qualified.
For example, if I tell the compiler to search directories lib1 and lib2 and the include is simply #include "c.h" and c.h exists in both directories, the compile will use the one it finds first.
However, if the includes are qualified as in your example, the compiler will have no problem distinguishing the two files.
1 2
#include "lib1/c.h"
#include "lib2/c.h"
Keep in mind that those file names are relative to the directory where your source is, so lib1 and lib2 must be directories under source directory. You can of course refer to a path relative to the parent directory or even use a fully qualified path name.
Also keep in mid that if c.h includes d.h and d.h exists in both directories, then the include of d.h (within c.h) must be similarly qualified.
As explained above, the compiler will search include directories in order, and choose the first "C.h" file it finds, which is incorrect.
You may not be able to modify the pre-compiled library code, but you always have the option to modify the header files.
Part of your confusion, I think, is that you are not clear about the separation between compile and link.
Sometime in the past, library files were compiled. They no longer need source code.
In the present, each one of your .cpp files needs to be compiled. It needs source code, including headers to tell the compiler how to compile your source to interface with the already-compiled libraries.
Once you have everything compiled to object files, plus the pre-compiled library code, the linker can now put it together to create an executable file.
So, the problem is that two header files conflict, since they use the same file name. When the original author of each library compiled his library, there was no conflict, because he did not have the other's library.
But you now need to deal with both. That's why your code must chose to include a more specific filename, such as stuff in the first example above.
the same paths -Ilib1 -Ilib2 are qualified in the compiler command line, but it gets an error:
g++ -Wall -Ilib1 -Ilib2 -c main.cpp -o obj/main.o
No, they are not "qualified". You're giving the compiler a list of places to search unqualified file names in order as I explained in the first example in my previous post. Since the include names are unqualified, the first c.h that is found will match. Since you specified lib1 before lib2 in the compiler directive, the compiler will look in lib1 first and will always find lib1/c.h.
When the include names are qualified (#include lib2/c.h), then compiler will only look there. There is no ambiguity and you don't need the -I options in the compiler directive.
Including both "lib1/C.h" and "lib2/C.h" made the compiler look in both libraries.
Where as including just <C.h>, the compiler stops searching after finding the first C.h it finds.