简体   繁体   English

导出编译时间常数,同时限制类的可见性

[英]Export a compile time constant, while limiting class visibility

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. 我使用的是C ++ 11之前的编译器,并且试图“导出”一个常量,而没有暴露从中计算该常量的类。

// 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 错误:“ Manager :: OverlayDataSize”不是类型为“ unsigned int”的有效模板参数,因为它是非恒定表达式

Which is already strange since Manager::OverlaySize most definitely is const and its value is calculated at compile time. 自从Manager::OverlaySize最肯定是const以来,这已经很奇怪了,并且它的值是在编译时计算的。 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. 但是根据问题,如果const声明及其定义不在同一位置,则编译器无法将其用作常量。 The error persists even if you use a global variable declared with extern . 即使您使用用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. 我可以通过使用联合来计算最大大小(但然后不允许结构AB具有构造函数),但这不是问题,我仍然无法导出该常量以在编译时可用将结构AB暴露给所有人。 Of course I can side step the whole issue by making the DataOverlay struct a bit more complicated and using new uint8[Manager::OverlayDataSize]; 当然,我可以通过使DataOverlay结构更复杂并使用new uint8[Manager::OverlayDataSize];来避免整个问题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 ? 那么,如何在保持结构ABManager用户之间严格分隔的同时“导出”编译时常量?

Here is a (rather ugly) solution. 这是一个(相当丑陋的)解决方案。

The core problem is you only need the size of A and B , which are constants, but you are forced to include the whole definition. 核心问题是您只需要AB的大小(它们是常量),但是您必须包括整个定义。 The solution would be to manually calculate the size and write it in the required place. 解决方案是手动计算尺寸并将其写入所需的位置。

But it is easy to forget to update the value when A and B are modified, so we should somehow automatically do the above job. 但是很容易忘记在修改AB后更新值,因此我们应该以某种方式自动完成上述工作。

To achieve this, you can write a code generator, which generates code like this to a header file: 为此,您可以编写一个代码生成器,将这样的代码生成到头文件中:

const size_t OverlayDataSize = /* the calculated size */;

and invoke that program each time you rebuild the whole project. 并在每次重建整个项目时调用该程序。 (For example, by writing a Makefile. ) (例如,通过编写一个Makefile。)

That generator can have A.hpp and B.hpp included, calculate max(sizeof(A), sizeof(B)) and run a printf or something similar to write the generated code. 该生成器可以包含A.hppB.hpp ,计算max(sizeof(A), sizeof(B))并运行printf或类似的操作来编写生成的代码。 The other source files should only #include the generated source. 其他源文件应仅#include生成的源。

Since C++ does not have a module system (which will enable you to hide some internal entities) or a complete metaprogramming facility (which allow us to write some code that generates other code), I can only think of this rather ugly way to achieve this. 由于C ++没有模块系统(可让您隐藏一些内部实体)或完整的元编程工具(可让我们编写一些可生成其他代码的代码),因此我只能想到这种相当丑陋的方式来实现此目的。 But anyway, it should work. 但是无论如何,它应该起作用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM