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); }
// ...
};
我正在开发一个插件,该插件在针对专有 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); }
// ...
};