【发布时间】:2022-01-17 20:14:29
【问题描述】:
我正在开发一个针对专有 PDK 在主机程序中运行的插件。 PDK 中有时会发生重大更改,因此我的代码使用包装器类,允许它与多个版本的主机一起工作,同时封装不同版本的更改。
这是一个非常简化的示例,说明了我想解决的问题。当然,我正在与更多的成员打交道 2。
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; }
我发布这个问题是为了看看是否有人有更好的想法,尤其是不涉及宏的想法。谢谢。
【问题讨论】:
-
已经有一个包装器:
std::variant -
我查看了
std::variant,但在没有 if 语句的情况下看不到如何在每个 getter 和 setter 中使用它。你有一个在这种情况下我将如何使用它的例子吗? -
我不确定我是否完全理解,但也许多态性会有所帮助? idea
-
我喜欢
std::visit的想法。二传手将如何工作? -
我相信您已经找到了
std::variant的文档。因此,您只需阅读文档中的给定示例并根据需要修改代码。有什么理由让我们再次重复这里的示例代码吗?