获取类中的静态属性数

时间:2012-04-19 08:05:02

标签: c++ sizeof static-members static-assert

我有一个由静态属性组成的类,作为一个穷人的单身人士。其目的是从应用程序的各个点收集统计数据。对于我们的单元测试,我创建了一个卷影副本,可用于区分生产代码中的一个。

示例:

struct Production {
    static ComplexClass value1;
    static ComplexClass value2;
};

struct ProductionShadow {
    static ComplexClass::ValueType value1;
    static ComplexClass::ValueType value2;
};

由于所有成员都是静态的,因此shadow类不能从生产类继承,而生产类中的属性是带有副作用的复杂对象,我只希望阴影保存简单的值以进行比较。

为了使影子类更容易维护,我想添加一个静态断言,以检查每当有人向生产类添加属性时,影子类也会更新。

如果属性不是静态的,可以通过以下方式轻松完成:

enum { NumberOfProductionAttributes = sizeof(Production) / sizeof(ComplexClass),
       NumberOfShadowAttributes = sizeof(ProductionShadow) / sizeof(ComplexClass::ValueType) };
STATIC_ASSERT(NumberOfProductionAttributes == NumberOfShadowAttributes);

除了使这些类非静态,我不愿意这样做,因为我必须将生产类变成一个合适的单例,有什么办法可以用当前的实现来完成这个检查吗? / p>

在运行时,我有一个方法可以使用生产类验证阴影中的所有值。由于在添加新属性时也必须更新该方法,因此我希望能够计算已验证的属性数量,并在数量与属性总数不同时断言。

实施例

bool ProductionShadow::verify() {
    std::size_t numberOfVerified = 0;
    #define VERIFY(x) do { \
        ++numberOfVerified; \
        // Verification code goes here \
    } while (0)
    VERIFY(value1);
    VERIFY(value2);
    ASSERT(numberOfVerified == NumberOfShadowAttributes);
    // Return result
}

如果有GCC扩展我可以使用,这可能是一个可接受的解决方案,即使我更喜欢便携式。

3 个答案:

答案 0 :(得分:1)

您可以混合使用inheritancetemplate

enum ClassType { DEFAULT, SHADOW };

template<ClassType E>
struct Production_T
{
  static ComplexClass value1;
  static ComplexClass value2;
};
typedef Production_T<DEFAULT> Production;

struct ProductionShadow : Production_T<SHADOW> {
  // add only new 'static' members, others are copied from 'Production_T'
};

如果某个成员被添加到Production_T,则ProductionShadow将自动更新。因此,您不必担心在ProductionShadow中重复成员。

答案 1 :(得分:1)

以防万一,这是我在问题评论中建议的解决方案。我们的想法是以非静态成员的形式创建两个包含问题的数据成员的类

struct ProductionStaticMembers
{
  ComplexClass value1;
  ComplexClass value2;
};

struct ProductionShadowStaticMembers
{
  ComplexClass::ValueType value1;
  ComplexClass::ValueType value2;
};

然后重新定义原始类以包含上面定义为静态成员的类。它们将继续像以前一样运行,并且可以针对上面定义的类型执行大小检查。

struct Production {
  static ProductionStaticMembers static_members;
};

struct ProductionShadow {
  static ProductionShadowStaticMembers static_members;
};

不可否认,这意味着改变静态成员的访问方式(因为他们现在是另一个成员的成员);因此,可能需要对现有代码进行许多更改。

答案 2 :(得分:0)

你可以用宏来做到这一点。它有点难看,但会起作用:

productiondecl.h

struct PRODUCTION_TYPE
{
    PRODUCTION_VAR(ComplexClass, value1);
    PRODUCTION_VAR(ComplexClass, value2);
};

production.h

#define PRODUCTION_TYPE Production
#define PRODUCTION_VAR(type,name) static type name;
#include "productiondecl.h"
#undef PRODUCTION_TYPE 
#undef PRODUCTION_VAR

productionshadow.h

#define PRODUCTION_TYPE ProductionShadow
#define PRODUCTION_VAR(type,name) static type::ValueType name;
#include "productiondecl.h"
#undef PRODUCTION_TYPE 
#undef PRODUCTION_VAR

如果你不能在每种情况下使用type :: ValueType,写一个元函数来阐明这个类型:

template <typename T>
struct ShadowType
{
    // default type is type::ValueType
    typedef T::ValueType type;
};
template <> ShadowType<SomeOtherType>
{
    typedef SomeOtherTypeShadow type;
}
#define PRODUCTION_VAR(type, name) static ShadowType<type>::type name;

或者,您可以避免使用宏并使用模板策略:

struct ComplexClass {
    typedef int ValueType;
};

template <typename T>
struct ShadowType
{
    typedef typename T::ValueType type;
};
template <typename T>
struct ProductionType
{
    typedef T type;
};

template <template <typename T> class Policy>
struct ProductionBase
{
    static typename Policy<ComplexClass>::type value1;
    static typename Policy<ComplexClass>::type value2;
};

struct Production : public ProductionBase<ProductionType>
{
};
struct ProductionShadow : public ProductionBase<ShadowType>
{
};

或者,一个可怕的黑客,使用宏来避免更改生产代码:

#define Production ProductionShadow
#define ComplexClass ComplexClass::ValueType
#include "production.h"
#undef Production 
#undef ComplexClass