Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ambiguous reference and namespace (clash of definitions from the two external libraries)

I experience the collapse of definitions i can't make sense of.

Schematically the problem is as follows:

The main project file has two includes:

include <lib1.h>
include <lib2.h>

The first header includes couple of other headers from the library, in one of those there is a direct (not covered with a name-space) definition:

template<typename T> class SparseMatrix;

The lib2.h has the following inside

namespace lib2
{
   using namespace lib3;

   class ...
   {
      ...
      SparseMatrix<double> ...
      ...
    }
}

Inside lib3, covered with the namespace, there is also a definition of SparseMatrix class.

Each library separately compiles with no problem. When I try to compile the executable which uses the, compiler produces an error:

lib2.h:70:7: error: reference to 'SparseMatrix' is ambiguous

Which looks strange to me since nowhere in the main program do I write

using namespace lib3;

Thus I see no reason why those definitions should collapse. I would greatly appreciate any possible explanation for the problem.

Of course, I can enclose the definitions from the lib1 into a their own namespace, but then I would need to modify quite a number of files there, which I would rather not do.

COMMENT: the answer below is correct but i was also able to get around the problem by changing the order of included files, i.e. first include lib2 and then lib1.

like image 976
Denis Avatar asked Mar 26 '13 14:03

Denis


1 Answers

nowhere in the main program do i write using namespace lib3;

But if you look in lib2.h, exactly that has been written. The contents of the lib3 namespace have been brought into lib2 and are now visible when defining the SparseMatrix<double> object.

You can think of lib2.h as being something like this after all includes have been resolved:

template <typename T> class SparseMatrix;    // (1)

namespace lib3
{
   template <typename T> class SparseMatrix; // (2)
}

namespace lib2
{
   using namespace lib3; // (3)

   class ...
   {
      ...
      SparseMatrix<double> ... // (4)
      // ::SparseMatrix<double> would only see (1)
      // lib2::SparseMatrix<double> would only see (2)
    }
}

The line marked (1) declares SparseMatrix which is immediately visible on line (4). The declaration on line (2) would not be, but since line (3) brings it into namespace lib2, it is now also visible on line (4).

You can get around this simply by fully qualifying the type:

::SparseMatrix<double> ...

:: with no preceding namespace denotes the global namespace.

The other alternative is to not have using namespace lib3; in lib2.h and properly qualify the contents of the lib3 namespace.

like image 156
Joseph Mansfield Avatar answered Oct 13 '22 19:10

Joseph Mansfield