Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I include header file within a namespace?

Tags:

c++

namespaces

Currently I am working on a c framework and I want to embed a c++ package into it. However, there are lots of naming conflicts occurs. So I decided to to add a namespace to the C++ source. Now the question is should I move the #include "header.h" within namespace { } block? I just spent some time to figure out a bug which was resulted from the following codes.

Original C++ source

In a.h

#include <unistd.h>
struct File 
{
     void func(int fd);
}; 

In a.cpp

#include "a.h"
void File::func(int fd)
{
    ::close( fd );
}

And I added the namespace like this

New a.h

namespace MyAddedNameSpace 
{ 
    #include <unistd.h>
    struct File 
    {
        void func(int fd);
    }; 
}

New a.cpp

#include "a.h"
namespace MyAddedNameSpace 
{
    void File::func(int fd)
    {
        ::close( fd );
    }
}

And compiler complains that ::close() has not been declared.

The reason Why I put the #include directive inside namespace block is because the c++ package I imported also use #ifndef flag to include header files as follows. So I think the easy way is to put all codes within namespace block {}

#ifndef 
    #include <header1.h> 
    #include <header2.h>
    ...
#else 
    #include <header3.h>
    #include <header4.h>
    ...
#endif

Now I solved this problem by adding the extra line in cpp file

#include <unistd.h>  //new added line 
#include "a.h"
namespace MyNameSpace 
{
    void File::func(int fd)
    {
        ::close( fd );
    }
}

But I am not satisfied with this solution since unistd.h header has already been included in a.h, but inside the namespace MyAddedNameSpace, or should I added the prefix MyNameSpace to all the function calls where the compiler complain no such function declared ?

Thanks for the reply.

like image 786
Christopher Avatar asked Mar 19 '12 03:03

Christopher


1 Answers

You SHOULD NOT place #include directives inside your own namespace. What you have done is to place all of the contents of unistd.h inside your namespace as well; thus what used to be (and should remain!) ::close() is now declared as MyAddedNameSpace::close(). This is NOT what you want.

Your "solution" of adding the line #include <unistd.h> at the top of your .cpp file fixes the problem, but only for this one .cpp file. What you've done is included the library header the correct way (without your namespace), and then when your header (a.h) is included, it does #include <unistd.h> again (this time within your namespace), but this time the include guards in that file prevent it from being processed again. So for this .cpp file you're OK, but any other file that does #include <a.h> will have the same problem that you originally had.

There may be some rare occasion where you have a good reason for using #include within your own namespace, but you will most likely be including one of your own headers (or some other file) - NOT a library header! - and even then, it's probably not the ideal solution.

In a.h

#include <unistd.h>

namespace MyAddedNameSpace {

struct File
{
  void func(int fd);
};

}

In a.cpp

#include "a.h"

namespace MyAddedNameSpace {

void File::func(int fd)
{
  ::close( fd );
}

}
like image 54
aldo Avatar answered Sep 23 '22 09:09

aldo