一个C++结构,它可以提高可读性,计算结果为零,但不是宏
A C++ construct which improves readability, evaluates to nothing but is NOT a macro
我有以下情况。我们正在编写一个库,它有一个类,它有很多字段(大部分),这取决于一些可选字段,如果可选字段存在与否,这些字段都有"标志"(基本上是数字中的位)。
类的字段必须是公共的,以便于访问(我知道这很糟糕),第三方开发人员将阅读头文件(除了他们的文档),以便熟悉各种字段的结构和与相应选项的连接。
问题是,客户希望让他们的开发人员尽可能轻松地识别哪些字段取决于哪个可选结构。
其中一种解决方案是在字段(类成员)名称的上方或之后添加注释,告诉它使用此选项字段。这是最基本的选择。
然而,这个类已经有大约500个成员(字段),所以我不知道添加额外的500行或长注释是否会提高它的质量
我们提出了以下结构:
#define DEPENDS
#define ON
#define BIT(x) ((x)-1)
#define OF(x)
struct source{};
struct options
{
options(const source&) {}
};
template <int BITIDX>
struct optional
{
optional(const options&) {}
};
struct something
{
// this constructor will be implemented in the CPP
// so the user (developer) will not see it
something (const source& src) :
msource(src), initial_options(src), other_options(src),
field1(initial_options), field2(other_options) {}
options initial_options;
options other_options;
optional<DEPENDS ON BIT(1) OF (initial_options)> field1;
optional<DEPENDS ON BIT(1) OF (other_options) > field2;
source msource;
};
int main()
{
source s;
something a(s);
}
但显然,由于名称空间污染、宏等原因,这并没有好到哪里去。。。
那么,问题是:有没有更好的方法来实现我们的目标,提供一种有意义的方式来从一个选项中呈现一个领域的连接?
(请注意,C++11类成员初始化是NOT允许的,否则我不会问这个问题:)我们必须坚持使用较旧的编译器:()
struct something
{
enum OptionGroup { Initial, Other /*...*/ };
enum InitialFields { A, B /*...*/ };
enum OtherFields { X, Y /*...*/ };
因此,我们列举了每个可选组中的字段A、B等。由于它们是从零开始递增的,枚举值会告诉我们哪个位代表每个字段。
template <typename TYPE, OptionGroup GROUP, int BIT>
struct Optional {
TYPE val;
operator TYPE& () { return val; }
operator TYPE const& () const { return val; }
};
这记录了一个可选字段的组,以及该组中的哪一位代表它。你没有说明字段的类型,所以我将其设为泛型。您也没有说明如何初始化它们,因此可能需要构造函数等
int mandatory1;
int initialOptions;
Optional<int, Initial, A> a;
Optional<int, Initial, B> b;
int otherOptions;
Optional<double, Other, X> x;
这里我们有一个强制性和可选字段序列的实际存储。
现在,我们需要一些方法来获得每个组的标志:
template <OptionGroup GROUP> int getGroupFlags();
有了它,我们可以检查给定字段是否有效。。。
template <typename TYPE, OptionGroup GROUP, int BIT>
bool isValid(Optional<TYPE,GROUP,BIT> const &field) {
return getGroupFlags<GROUP>() & (1 << BIT);
}
};
遗憾的是,记录枚举和组之间的关联仍然是手动的(这就是能够将两组选项标志合并到一个位字段中会让生活变得更容易的地方)
template <> int something::getGroupFlags<something::Initial>() { return intialOptions; }
template <> int something::getGroupFlags<something::Other>() { return otherOptions; }
这可以得到很大的清理(例如,通过将每个可选组绑定到一个单独的结构中,而不是对讨厌的OptionGroup->flag字段关系进行硬编码),但这似乎是最少的工作。
- 为什么"do while"循环不断退出,即使条件计算结果为 false?
- 计算幂级数的数学结果不正确
- 当我的 if 条件计算结果为 false 时,我的 else 块将不会执行
- 为什么组合的上限和下限比较的计算结果总是为 true?
- 为什么'typeid(x) == typeid(y)'的计算结果为 true,其中 'x' 和 'y' 分别是 T 和 T& 类型的 id-表达式?
- 在Javascript和C++中计算MD5哈希的不同结果
- 为什么 Lisp 中 1000 阶乘的计算如此之快(并显示正确的结果)?
- 我们如何并行运行算法的 n 个实例并以有效的方式计算结果函数的平均值?
- Fmod 函数清楚地输出一个预期的双精度值,但 if(fmod == 预期的双精度值)的计算结果不是 true
- WebGL2 和 C++ 上的浮点计算结果不同
- 术语的计算结果不是采用0个参数的函数
- C++编译器能在编译时计算出文字的除法结果吗
- 错误 C2064:术语的计算结果不是采用 3 个参数的函数
- 在C++中,是否可以编写一个条件的lambda,即只是一个计算结果为真或假的条件
- C++ 函数指针的计算结果为 1
- 为什么 02000 的计算结果为 1024
- 为什么这两个相似的代码计算行列式的结果不同?
- C++ openmp 并行计算计算错误的结果
- 如何让编译器忽略这个计算结果为 false 的 if-constexpr?
- 从文本文件中读取并使用 sizeof 结果计算整数的数量到 nan