如何确定某个内容是否已添加到结构中

How to determine if something was added to a struct?

本文关键字:添加 结构 是否 何确定      更新时间:2023-10-16

我有几个小结构和一个包含它们的大结构:

struct A
{
...
};
struct B
{
...
};
struct AB
{
A a;
B b;
};

在代码的不同位置,我得到了一个AB变量,并对AB.aAB.b进行了处理。我想确保,如果有人向AB添加结构,他也会更新使用AB的代码。

所以我的问题是我该如何检查?

我知道我不能信任sizeof并做一些类似的事情:

 sizeof(AB)==sizeof(a)+sizeof(b)

我应该提到的是,我并不真正关心小结构是什么,只关心AB中有多少。

有什么建议吗?

谢谢!

编辑:如果我假设A和B只包含基元,如果我检查:怎么办

offset(last member of B)+sizeof(last member of B)==sizeof(AB)

你觉得怎么样?

对于C++,一个可能的选择是使用模板和Boost。融合

我们使用和一个boost::fusion::vector作为聚合类:

typename boost::fusion::vector<A,B> Aggregate;

让我们假设我们有一个应该在所有部件上执行的操作:

struct Operation {
    void operator()(A& a) { ... } // operation for A
    void operator()(B& b) { ... } // operation for B
};

Boost Fusion为一个类型容器的所有部分提供了一个简单迭代的功能:

Aggregate x;
boost::fusion::for_each(x, Operation());   

如果您现在将聚合扩展到boost::fusion::vector<A,B,C>,那么当您没有为类型C提供Operation::operator()的重载时,将出现编译器错误。


工作示例:

#include <iostream>
#include <boost/fusion/include/for_each.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/include/at_c.hpp>
namespace bf = boost::fusion;
struct A { int a; };
struct B { float q; };
typedef bf::vector<A,B> MyClass;
struct IncrementOp {
    void operator()(A& x) const { x.a ++; }
    void operator()(B& x) const { x.q += 1.0f; }
};
int main() {
    MyClass c;
    bf::at_c<0>(c).a = 0;
    bf::at_c<1>(c).q = 4.2f;
    bf::for_each(c, IncrementOp());
    std::cout << bf::at_c<0>(c).a << std::endl;
    std::cout << bf::at_c<1>(c).q << std::endl;
}

不会直接回答您的问题,但说明了如何管理对struct的更改,而不必担心随着时间的推移添加成员。

(注意,这些想法不适用于删除成员)

使用 struct构造(而不是使用离散类型)的一个实质性好处正是您所要求的:在不破坏代码的情况下添加成员的能力struct类型可以使代码的旧版本不需要添加额外的必需变量。也就是说,您可以将成员添加到全局定义的结构中,而无需强制更改将其包含在参数列表中的任何函数的原型。

例如 :给定具有以下结构的场景:

(注意,我使用typedef,这样声明在参数列表中会更短,并添加了真实成员)

这里 是您的原始场景:

typedef struct 
{
    int a1;
    int a2;
}A;
typedef struct 
{
    int b1;
    int b2;
}B;
typedef struct   //small change for less text in prototypes
{
    A a;
    B b;
}AB;  

这里是两个使用结构AB 的函数

这是为在对原始AB进行任何修改之前使用而写的:(目前不需要新成员)

void func1(AB var_old)
{
    var_old.a.a1 = 3;
    var_old.a.a2 = 3;
    var_old.b.b1 = 4;
    var_old.b.b2 = 4;
    //Note:  if var_old.b.b3 is ever needed here, it is available without changing prototype
}

稍后创建(或修改)一个需要新变量的函数

将成员添加到结构B:

typedef struct 
{
    int b1;
    int b2;
    int b3;
}B;  

在这里使用:

void func2(AB var_new)
{
     var_new.a.a2 = 10;//pre-existing member
     var_new.b.b3 = 4; //new member
}

原型参数列表没有更改,从而避免了编辑使用AB的每个函数的需要。

我发现并目前正在使用的解决方案是以下检查:

if !(sizeof(A+B) + 3 >= sizeof(AB)){
  return error;
}

我有一些松弛假设,使这个条件成为我的问题的解决方案:

  1. 单词大小=4
  2. 我所有的小结构(即A和B)都足够大,并且包含一个具有size>=4的成员,这确保了大结构省略4
  3. 结构AB仅包含结构

在这种情况下,如果有人在不改变这个条件的情况下向AB添加第三个结构C,他将得到一个错误(即使sizeof(c)<3是因为对齐)。这正是我想要的。