c++ - 导出编译时间常数,同时限制类可见性
问题描述
我正在使用 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);
....
}
上面的代码不会编译并导致:
错误:“Manager::OverlayDataSize”不是“unsigned int”类型的有效模板参数,因为它是非常量表达式
这已经很奇怪了,因为它Manager::OverlaySize
肯定是const
并且它的值是在编译时计算的。但是根据这个问题,如果const
声明及其定义不在同一位置,则编译器不能将其用作常量。即使您使用以 . 声明的全局变量,错误仍然存在extern
。我可以通过使用联合(但然后是结构A
并且B
不允许有构造函数)以不同的方式计算最大大小,但这不是问题,我仍然无法在不暴露结构的情况下导出该常量以在编译时可用A
和B
每个人。当然,我可以通过使 DataOverlay 结构更复杂并使用new uint8[Manager::OverlayDataSize];
在运行时并能够保持严格的分离。但我正在为此在编译时静态完成。
那么如何“导出”一个编译时常量,同时保持结构和用户之间A
的B
严格分离Manager
?
解决方案
这是一个(相当丑陋的)解决方案。
核心问题是您只需要 和 的大小A
,B
它们是常量,但您被迫包含整个定义。解决方案是手动计算大小并将其写入所需的位置。
但是很容易忘记在A
和B
被修改时更新值,所以我们应该以某种方式自动完成上述工作。
为此,您可以编写一个代码生成器,它将这样的代码生成到一个头文件中:
const size_t OverlayDataSize = /* the calculated size */;
并在每次重建整个项目时调用该程序。(例如,通过编写 Makefile。)
该生成器可以包含、计算A.hpp
和运行一个或类似的东西来编写生成的代码。其他源文件应该只是生成的源。B.hpp
max(sizeof(A), sizeof(B))
printf
#include
由于 C++ 没有模块系统(可以让您隐藏一些内部实体)或完整的元编程工具(允许我们编写一些生成其他代码的代码),我只能想到这种相当丑陋的方式来实现这一点. 但无论如何,它应该工作。
推荐阅读
- pivot-table - Google Data Studio:如果单元格中的记录少于 x,是否可以在数据透视表中过滤结果?
- javascript - 如何防止 Google 地方信息返回阿拉伯语地址?
- mysql - 优化 - 在循环内从 TEMP TABLE 中选择以获取 JSON 值平均值的函数
- javascript - 反应路由器,好奇它如何在没有哈希的情况下进行 url 导航
- git - Laravel 5.5 应用程序在任何内容之前输出一个 0
- c - 比较c语言中的有符号和无符号整数
- google-apps-script - List Google app script projects
- javascript - 节点集群示例在生产构建中失败
- node.js - 如何让 NGINX 接受 http://npomf/ 作为 proxy_pass?
- android - 居中对齐微调器提示文本