如何确定是否有东西被添加到结构中?

时间:2014-04-23 12:37:47

标签: c++ c struct sizeof

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

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)

您怎么看?

3 个答案:

答案 0 :(得分:1)

使用C ++,可能的选择是使用模板和Boost.Fusion

我们使用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>,那么当您没有为类型Operation::operator()提供C的重载时,您将收到编译器错误。


工作示例:

#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;
}

答案 1 :(得分:0)

不会直接回答您的问题,但说明了如何管理对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;  

这里 是两个使用struct 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的每个函数。

答案 2 :(得分:0)

我找到并正在使用的解决方案是以下检查:

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

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

  1. 字号= 4
  2. 我所有的小结构(即A和B)都足够大,并且包含一个size>=4的成员 - 这可以确保4个结构的大结构
  3. Struct AB仅包含结构
  4. 在这种情况下,如果有人在不更改此条件的情况下添加AB第三个结构C,他就会收到错误(即使sizeof(c)<3因为{{1}}对齐)。这正是我想要的。