I'm trying to wrap a C library in C++, to make it a modern, high level and idiomatic C++ library. What I want to do, is to make the C objects completely opaque and/or directly unavailable from the C++ code and wrap/replace them with higher-level alternatives.
The problem I'm facing with is simple: I want to include the C header only to the C++ source, so that the C++ header when included won't include the C header's declarations as well, that is, it won't pollute the global namespace.
But it looks like the correct separation of the header and source files does not allow me to do that. Here is a very much dummified version of my problem, the comments will tell you the rest:
my_header.h:
typedef enum
{
my_Consts_ALPHA = /* some special value */,
my_Consts_BETA = /* other special value */,
} my_Consts;
typedef struct
{
// members...
} my_Type;
void
my_Type_method(my_Type *const,
my_Enum);
my_header.hpp:
namespace my
{
enum class Consts; // <-- This header is missing the constant values of
// this enum, because its values are defined by
// the C header :(
class Type : public my_Type // <-- The super struct is coming from the
// C header, but I don't want to include
// that header here :(
{
public:
void
method(Consts constant);
};
}
my_source.cpp:
extern "C"
{
#include "my_header.h"
}
#include "my_header.hpp"
namespace my
{
enum class Consts
{
ALPHA = my_Consts_ALPHA,
BETA = my_Consts_BETA,
};
void
Type::method(Consts constant)
{
my_Type_method(static_cast<my_Type *const>(this),
static_cast<my_Consts>(constant));
}
}
So my questions are: am I missing something very obvious here? Is this even possible to achieve? Is there a trick that I'm not aware of?
namespace m00 {#include "myheader.h"}
(yes, this is partially sarcastic) – Davenstruct Consts{enum values{/*values mirroring C consts struct here*/}};
which would allow you to convert from and to the underlying type, then write a specialized cast to convert between the two enums in your .cpp file. – Coucalenum class
es which I truly want to use :) Not to mention, the lightness of an enum compared to a struct.. – Rookeextern "C"
names are usually not mangled. – Muniz.hpp
, so in some ways, it answers my question, that those values won't pollute the global namespace, but on the other hand they will not hide/restrict access to them, right? – Rookenamespace ...
? I thought the namespace is part of the name mangling. Lets say, I include two C-header files which both define the name foo and souround them with two different namespaces. How does the linker resolve a call tonamespace1::foo
then? – Achermanextern "C"
is C compatibility. C doesn't mangle. If you include two such things, you will have an error. The linker would see both names as justfoo
and will not be able to resolve them correctly. – Muniz