【发布时间】:2020-06-29 03:55:27
【问题描述】:
| ■ 问题定义____________________
我正在尝试设计一个满足以下属性的超级灵活但内存高效的模块。
- 它可以根据情况关闭不必要的成员变量。
- 它将拥有哪些变量在编译时确定。
我用宏和枚举器标志“在”编译时间做了一个确定其成员列表的方法/强>。见下文:
▼ TraitSwitch.h
#pragma once
// Macros to switch-off source codes themselves.
#define ON 1
#define OFF 0
#define TRI_AREA_INFO ON
#define TRI_CENTROID_INFO ON
#define TRI_NORMAL_INFO OFF // When the normal vector info is unnecessary.
...
▼ TriangleTraits.h
#pragma once
#include <cstdint>
#include "TraitSwitch.h"
enum TriangleTrait : uint8_t
{
NONE = 0, // 0000 0000
#if (TRI_AREA_INFO == ON)
AREA = 1, // 0000 0001
#endif
#if (TRI_CENTROID_INFO == ON)
CENTROID = 2, // 0000 0010
#endif
#if (TRI_NORMAL_INFO == ON) // | Inactive Preprocessor Block
NORMAL_VECTOR = 4, // 0000 0100 |
#endif
... // more traits
ALL = 255 // 1111 1111
}
// Need some additional overloaded bitwise-operators (&, |, |=, etc ...)
▼ Triangle.h
#pragma once
#include "TriangleTraits.h"
class Triangle
{
public:
Triangle() {}
~Triangle() {}
#if (TRI_AREA_INFO == ON)
double area;
#endif
#if (TRI_CENTROID_INFO == ON)
double centroid[3]; // x, y, z
#endif
#if (TRI_NORMAL_INFO == ON) // | Inactive Preprocessor Block
double normal[3]; // x, y, z |
#endif
...
TriangleTrait alreadyComputed; // To avoid redundant works.
void ComputeTraits(TriangleTrait _requested)
{
if (((_requested & TriangleTrait::AREA) != 0)
&& ((alreadyComputed & _requested) == 0))
{
this->ComputeArea();
alreadyComputed |= TriangleTrait::AREA;
}
... // do the same things for centroid, normal
}
private:
void ComputeArea();
void ComputeCentroid();
void ComputeNormal();
...
}
那么,对象上的C++ IntelliSense可能会显示:this
▼ main.cpp
#include <iostream>
#include "Triangle.h"
int main(void)
{
Triangle tri;
tri.ComputeTraits(TriangleTrait::AREA | TriangleTrait::CENTROID);
std::cout << "area : " << tri.area << "m²" << std::endl;
std::cout << "centroid : ("
<< tri.centroid[0] << ","
<< tri.centroid[1] << ","
<< tri.centroid[2] << ")" << std::endl;
...
}
首先Triangle.h看起来挺难看的,就算好看,这个方法也判断类成员"before"无论如何,编译时。
| ■ 问题摘要____________________
“如何设计具有可切换成员的模板类,这些成员在编译时确定。”
这正是我想要的:
▼ main.cpp
...
int main(void)
{
Triangle<__MACRO_DEFINED_TRAIT_SWITCH(AREA)> tri1; // This owns area info only
tri1.area;
Triangle<__MACRO_DEFINED_TRAIT_SWITCH(AREA | CENTROID)> tri2; // This owns area & centroid info
tri2.area;
tri2.centroid;
Triangle<__MACRO_DEFINED_TRAIT_SWITCH(AREA | NORMAL)> tri3; // This owns area & normal vector info
tri3.area;
tri3.normal;
...
Triangle<__MACRO_DEFINED_TRAIT_SWITCH(AREA | CENTROID | NORMAL)> tri4; // This owns area & centroid & normal vector info
tri4.area;
tri4.centroid;
tri4.normal;
...
}
我猜想使用 模板与宏 结合(使用 标签调度 方法,也许?)将完全符合我的要求,但没有任何明确的想法。
【问题讨论】:
-
'在运行时确定'。由于模板类是在编译时确定的,因此您将永远无法在运行时确定它(显然对于宏也是如此)。这似乎是一个死胡同。
-
@Jean 哦,我很困惑 3:编译前 & 编译时 & 运行时 .我会立即编辑我的问题。感谢您指出我的愚蠢错误! :D
-
听起来像你想要的
std::tuple。 -
@L.F. |是的,当然
std::tuple很简单,很好。但我认为调用像double& area = std::get<0>(tri)这样的每个特征并不能提供很好的代码可读性。另外,参数的顺序对它来说太关键了。:(
标签: c++ c++11 templates visual-c++