I'm using a pre-C++11 compiler and I'm trying to "export" a constant, without exposing the classes from which this constant is calculated.
// A.hpp ----------------------
struct A{
...
};
// B.hpp ----------------------
struct B{
...
};
// Manager.hpp ------------------
#include "Manager.hpp"
template <size_t a, size_t b>
struct StaticMax
{
enum { value = a>b ? a : b };
}
class Manager
{
public:
static const size_t OverlayDataSize;
...
};
// manager.cpp ------------------
#include "A.hpp"
#include "B.hpp"
// I want the following constant to be available to anyone
// that includes Manager.hpp, but the classes A and B should not
// be visible to anyone else except class Manager
const size_t Manager::OverlayDataSize = StaticMax<sizeof(A),sizeof(B)>::value;
// otherfile.hpp -------------------
#include "Manager.hpp"
struct OverlayData
{
// shared state goes here
uint8 gameState;
uint8 specificState[Manager::OverlayDataSize];
};
class NvRam
{
void Write(OverlayData& serializedState);
....
}
The above code won't compile and results in:
error: ‘Manager::OverlayDataSize' is not a valid template argument for type ‘unsigned int’ because it is a non-constant expression
Which is already strange since Manager::OverlaySize
most definitely is const
and its value is calculated at compile time. But according to this question, if a const
declaration and its definition aren't in the same location, then the compiler can't use it as a constant. The error persists even if you use a global variable declared with extern
. I could have calculated the maximum size differently by using a union (but then structs A
and B
aren't allowed to have constructors), but that's not the problem, I still can't export that constant to be available at compile-time without exposing structs A
and B
to everyone. Of course I can side step the whole issue by making the DataOverlay struct a bit more complicated and using new uint8[Manager::OverlayDataSize];
at runtime and be able to maintain strict seperation. But I'm shooting for this to be done statically at compile time.
So how to "export" a compile-time constant while maintaining strict separation between structs A
and B
and users of Manager
?