2012-04-19 8 views
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の拡張機能がある場合。

+1

2つのグローバルインスタンスを持つ単一のクラスを持たない理由はありますか? – Pete

+0

2つのクラスでタイプが異なります。これは、制作者がシャドーコピーで複製したくない副作用を伴う複雑なクラスを保持するためです。影は比較のために使用される値だけを保持しているはずです。私は問題の説明を更新します。 –

+1

静的でないメンバーを持つ2つの別々のクラスを作成し、それらの静的インスタンスを2つのクラスに入れることができます。次に、非静的メンバーを持つ元のクラスに対してサイズチェックを実行できます。 – jogojapan

答えて

1

ちょうど場合には、ここに私が質問へのコメントで提案した解決策があります。

struct ProductionStaticMembers 
{ 
    ComplexClass value1; 
    ComplexClass value2; 
}; 

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

そして静的メンバとして上記で定義されたクラスを含むように、元のクラスを再定義:アイデアは、非静的メンバの形で質問にデータメンバが含まれている2つのクラスを作成することです。以前と同じように機能し続け、上記で定義した型に対してサイズチェックを実行できます。

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

+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にメンバーを複製することについて心配する必要はありません。

+0

興味深い解決策ですが、シャドウ内のヘルパーメソッドのすべての属性を処理したことを確認することはできません。 –

+0

@DavidHolm、私はあなたの新しい質問をしないでください。なぜ、何を確認したいのですか? – iammilind

+0

シャドウ内の検証メソッド(ユニットテストで使用される)が実際にすべてのシャドウ値を実動クラスのすべての値と照合することを確認します。これらのチェックは手動でこれらのメソッドに追加する必要があるため、簡単に忘れてしまいます。 –

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。時間

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

あなたはすべてのケースでタイプ:: ValueTypeにを使用するカント場合は、タイプをelucdiateするメタ関数を書く:

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; 

OR、あなたがマクロを回避し、テンプレートのポリシーを使用できます。

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 
関連する問題