我正在开发一个插件,它运行在一个针对专用PDK的主机程序中。有时,PDK中会有不同的更改,所以我的代码使用包装器类,允许它处理多个版本的主机,同时封装不同版本的更改。
这里有一个非常简单的例子,说明了我想要解决的问题。当然,我要和更多的成员打交道。
struct DataV1 // I cannot modify this
{
int a;
float b;
};
struct DataV2 // I cannot modify this
{
float b;
int a;
long c;
};
class DataWrapper // my class
{
private:
bool _forV1; // determined at run-time
DataV1 _dataV1;
DataV2 _dataV2;
public:
DataWrapper(); // initializes _forV1
int GetA() const;
void SetA(int value);
float GetB() const;
void SetB(float value);
long GetC() const { return _dataV2.c } // only exists in v2
void SetC(long value) { _dataV2.c = value; } // only exists in v2
};我希望避免在每个getter和setter中重复从结构的一个版本或另一个版本中选择成员的逻辑。注意,当重新排列成员的顺序时,类型和成员名称是相同的。我想出了一个宏:
#define DATA_ACCESS(MEMBER) const_cast<decltype(_dataV1.MEMBER)&>(([&]() -> const decltype(_dataV1.MEMBER)& \
{ return (_forV1) ? _dataV1.MEMBER : _dataV2.MEMBER; })())这允许对属性访问器函数进行某种优雅的实现:
int GetA() const { return DATA_ACCESS(a); }
void SetA(int value) { DATA_ACCESS(a) = value; }
float GetB() const { return DATA_ACCESS(b); }
void SetB(float value) { DATA_ACCESS(b) = value; }我发这个问题是为了看看是否有人有更好的想法,尤其是一个不涉及宏的想法。谢谢。
发布于 2021-12-14 17:00:36
使用std::variant,您可以执行如下操作:
class DataWrapper // my class
{
private:
std::variant<DataV1, DataV2> data;
public:
DataWrapper(); // initializes _forV1
int GetA() const { return std::visit([](auto& arg){ return arg.a; }, data); }
void SetA(int a) const { std::visit([&a](auto& arg){ arg.a = a; }, data); }
// ...
};https://stackoverflow.com/questions/70350208
复制相似问题