If I am creating a library that exposes one public header file, which may take or return a publicly exposed enum
, how would I use that enum
internally without also creating a circular dependency in header files?
For example :
Public.h
#include "Internal.h"
namespace PublicFunctions {
enum Access{
READ,
WRITE,
}
FileObject CreateFileObject(Access a) {
return InternalFunctions::GetFileObject(a);
}
}
Internal.h
#include "Public.h"
namespace InternalFunctions {
FileObject GetFileObject(PublicFunctions::Access a);
}
Internal.cpp
FileObject InternalFunctions::GetFileObject(PublicFunctions::Access a) {
if (a == PublicFunctions::Read) {
return openreadonly();
}
else {
return openwrite();
}
}
I know about the #praga
once preprocessor directive, but is there any way to forward declare an enum
in these internal files ?
Or is #pragma
once the best method to resolve these dependencies ?
An include guard cannot help you because if public.h is included first, the logical case for the library's clients, you will wind up with
// public.h already included so #include "Public.h" is ignored
namespace InternalFunctions {
FileObject GetFileObject(PublicFunctions::Access a);
// PublicFunctions::Access not defined yet.
}
namespace PublicFunctions {
enum Access{
READ,
WRITE,
}
FileObject CreateFileObject(Access a) {
return InternalFunctions::GetFileObject(a);
}
}
Worse anyone who includes public.h gets a peek into internals.h, which defeats the point of separating the two.
But if you remove CreateFileObject
's implementation from public.h you can
namespace PublicFunctions {
enum Access{
READ,
WRITE,
}
FileObject CreateFileObject(Access a);
}
and leave internal.h alone. It will be used exclusively by the compiled library and not be shipped with the public interface.
#include "Public.h"
namespace InternalFunctions {
FileObject GetFileObject(PublicFunctions::Access a);
}
and then Internal.cpp
#include "internal.h"
FileObject InternalFunctions::GetFileObject(PublicFunctions::Access a) {
if (a == PublicFunctions::Read) {
return openreadonly();
}
else {
return openwrite();
}
}
and finally public.cpp
#include "internal.h"
FileObject PublicFunctions::CreateFileObject(Access a) {
return InternalFunctions::GetFileObject(a);
}
Whether it is worth separating public.cpp and internal.cpp is up to the programmer and their coding standard.