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?
OverlayDataSize, you must have its definition in scope, and thus requiringAandBin scope. - Ruifeng XieOverlayDataSizeis calculated at compile time, I see no reason in principle this couldn't be done, but it'd probably require putting in placeholders for the constants and going back over the compiled code and replacing placeholders once the compiler makes the needed calculation... - jhuffordAandBused for anything else? Given the way the code is set up I expect they are, but in that case I'm not sure why you want to go to the effort of hiding them when whatever included"Manager.hpp"could also just include"A.hpp"and"B.hpp". If they aren't, you can make them internalprivatemember classes ofManager. - Daniel H