4

私は、一種の貧しい人のシングルトンとして機能する静的属性のみで構成されるクラスを持っています。その目的は、アプリケーションのさまざまなポイントから統計を収集することです。単体テストでは、実稼働コードとの違いを取得するために使用できるシャドウ コピーを作成しました。

例:

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

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

すべてのメンバーは静的であるため、シャドウ クラスはプロダクション クラスから継承できず、プロダクション クラスの属性は副作用のある複雑なオブジェクトであり、比較のためにシャドウに単純な値のみを保持させたいと考えています。

シャドウ クラスの保守をいくらか容易にするために、静的アサートを追加して、誰かがプロダクション クラスに属性を追加するたびにシャドウ クラスも更新されることを確認したいと考えました。

属性が静的でない場合、これは次のようにすることで簡単に達成できたはずです。

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

クラスを非静的にする以外に、本番クラスを適切なシングルトンに変換する必要があるため、実行したくないのですが、現在の実装でこのチェックを実行できる方法はありますか?

実行時に、シャドウ内のすべての値を本番クラスで検証するメソッドがあります。新しい属性が追加されたときにメソッドも更新する必要があるため、検証された属性の数を数え、その量が属性の総数と異なるかどうかをアサートできるようにしたいと考えています。

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 拡張機能があれば、移植可能なものを好みますが、それは許容できる解決策になるかもしれません。

4

3 に答える 3

1

inheritanceとを組み合わせて使用​​できますtemplate

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

于 2012-04-19T08:21:17.050 に答える
1

念のため、質問へのコメントで提案した解決策を次に示します。アイデアは、問題のデータ メンバーを非静的メンバーの形式で含む 2 つのクラスを作成することです。

struct ProductionStaticMembers
{
  ComplexClass value1;
  ComplexClass value2;
};

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

次に、元のクラスを再定義して、上で定義したクラスをstatic membersとして含めます。これらは以前と同様に機能し続け、上記で定義された型に対してサイズ チェックを実行できます。

struct Production {
  static ProductionStaticMembers static_members;
};

struct ProductionShadow {
  static ProductionShadowStaticMembers static_members;
};

確かに、これは静的メンバーへのアクセス方法の変更を意味します (静的メンバーは別のメンバーのメンバーになったため)。したがって、既存のコードに多くの変更が必要になる場合があります。

于 2012-04-19T08:29:17.110 に答える
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
于 2012-04-19T08:27:27.103 に答える