C++ 使用宏或模板从 2 个结构之一返回成员

C++ Returning a member from one of 2 structs using macros or templates

我正在开发一个插件,该插件在针对专有 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,您可以执行以下操作:

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); }
    // ...
};