definition____________________
我试图设计一个超级灵活,但内存高效的模块满足以下属性.
我以某种方式做出了一个确定其成员列表"before“的编译时,使用宏和枚举器标志。见下文:
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可能会显示:这
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;
...
}首先,"before" Triangle.h看起来很难看,即使它看起来不错,这个方法还是确定了类成员编译时。
=问题summary____________________
“如何使用可切换成员__设计模板类,这些成员在编译时__中确定为。”
我最想要的就是:
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;
...
}我猜使用模板与宏相结合(可能是使用标记分派方法?)会做我想做的事,但没有任何明确的想法。
发布于 2020-03-20 03:36:46
经历了几天的痛苦之后,我找到了一条路。所以我自己回答我的问题。
这个想法太简单了。只需将多项继承与可变模板结合使用即可。见下文:
▼TriangleTraits.h
struct AREA
{
double area;
};
struct CENTROID
{
double centroid[3];
};
struct NORMAL
{
double normal[3];
};
... // more traits
// Multiple Inheritances with variadic template
template<class... Traits>
struct TriangleWithTraits : Traits...
{
};main.cpp
#include "TriangleTraits.h" // Just include this one is enough
int main()
{
TriangleWithTraits<AREA> tri1;
tri1.area;
TriangleWithTraits<AREA, CENTROID> tri2;
tri2.area;
tri2.centroid;
TriangleWithTraits<AREA, NORMAL> tri3;
tri3.area;
tri3.normal;
TriangleWithTraits<AREA, CENTROID, NORMAL> tri4;
tri4.area;
tri4.normal;
tri4.centroid;
...
}发布于 2020-03-19 04:06:04
不能使用预处理器解析模板参数,预处理器不知道C++。
但是有std::conditional和空的基优化。
因此,您可以使用数据类部件和std::conditional在它们和空基之间进行选择:
struct EmptyBase {};
struct BaseWithChar
{
char a;
};
struct BaseWithLongLong
{
long long b;
long long c;
};
template<int Flags>
struct A
: std::conditional<(Flags & 1), BaseWithChar, EmptyBase>::type
, std::conditional<(Flags & 2), BaseWithLongLong, EmptyBase>::type
{
};
int main() {
std::cout << sizeof(A<1>) << std::endl;
std::cout << sizeof(A<2>) << std::endl;
std::cout << sizeof(A<3>) << std::endl;
return 0;
}在后来的C++标准中,有std::coditional_t和[[no_unique_address]]
using namespace std;
struct EmptyMember {};
template<int Flags>
struct A
{
[[no_unique_address]] typename std::conditional_t<(Flags & 1), char, EmptyMember> a;
[[no_unique_address]] typename std::conditional_t<(Flags & 2), long long, EmptyMember> b;
[[no_unique_address]] typename std::conditional_t<(Flags & 2), long long, EmptyMember> c;
};
int main() {
std::cout << sizeof(A<1>) << std::endl;
std::cout << sizeof(A<2>) << std::endl;
std::cout << sizeof(A<3>) << std::endl;
return 0;
}但是[[no_unique_address]]需要C++20,如果没有[[no_unique_address]],空成员将占用一些空间。看起来它不适用于VisualC++,甚至是2019年预览版。我发了菲巴达克。
使用早期的C++,当您没有std::conditional或boost::conditional时,您可以很容易地实现自己的,它只是一个具有真和假专门化的模板。参见偏好页上的“可能实现”
https://stackoverflow.com/questions/60733043
复制相似问题