最近、ORM反射にブーストミラーを使用し始めたので、DB関連のボイラープレートコードの量を最小限に抑えることができます。
私が遭遇したパターンの1つを以下に示します。
Bar
のコードは、でも同じように見えるので、Baz
疑問に思っていましたが、このコードをさらに折りたたむことは可能ですか?
インターフェイスが同じように見えるといいのですgetValues()
が、代わりに同じ実装を使用することもできFoo
ます。
#include <iostream>
template< typename T >
struct Foo
{
static std::ostream& GetValues_Worker( std::ostream& os, T const& t )
{
// do boost mirror reflection stuff here
return os;
}
};
struct Bar :
public Foo<Bar>
{
// REFACTOR IF POSSIBLE: this code will always look the same - even for Baz
std::ostream&
getValues( std::ostream& os ) const
{
return GetValues_Worker( os, *this );
}
};
struct Baz :
public Foo<Baz>
{
// REFACTOR IF POSSIBLE: looks the same as Bar
std::ostream&
getValues( std::ostream& os ) const
{
return GetValues_Worker( os, *this );
}
};
int main( int argc, char* argv[] )
{
Bar b;
std::cerr << b.getValues( std::cerr ) << std::endl;
}
答え
以下のecatmurの答えはほとんどの場合うまくいくことがわかります。私の特定の状況では、彼のソリューションを実際のコードに適合させました。4つのケースのうち2つで機能しました。それが機能しなかった2つのケースでは、上記のミッキーマウスの例の範囲を少し超えていました。私が得ていたコンパイル時エラーを説明するSOで見つけた最も近い説明は、おそらくこの投稿です。問題の核心は、私のワーカーコード内で起こっていたことに関連しているように見えました。失敗した2つのケースでは、ブーストミラーの実行時リフレクションの結果から取得した内容に基づいて、サブクラスのメンバーの出力ストリーミングを実行していました。これは推論できない文脈の場合であることが判明したと思います。これらの2つの失敗したケースの解決策が正確に機能する理由はまだわかりません(仮想メソッドの形式でビジターを使用すると問題が回避される理由)。とにかく、私はそのアプローチに出くわし、コードをもう少し削減しようとしましたが(これらの4つのケースでは)、そのうちの2つでは、推論できないコンテキストの問題に遭遇することなく、そのコードをこれ以上削減できませんでした。