我最近开始使用boost mirror进行ORM反射,因此我可以最大限度地减少与DB相关的样板代码的数量。
我遇到过的一种模式如下所示。
由于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;
}
ANSWER
事实证明,ecatmur的答案在大多数情况下都适用。在我的具体情况下,我将他的解决方案改编为我的实际代码,它在4个案例中有2个工作。在它无法工作的两种情况下,它有点超出了我上面给出的Mickey-Mouse示例的范围。我在SO中找到的最接近的解释是解释我得到的编译时错误可能是this post。问题的关键似乎与我的工作人员代码中发生的事情有关。在两个失败的案例中,我根据我从提升镜像中的运行时反射结果返回的内容,对子类成员进行输出流式处理。我认为这是不可导出的背景的情况。我仍然不明白为什么这两个失败案例中的解决方案完全正常工作(为什么以虚拟方法的形式使用访问者来解决问题)。无论如何,我偶然发现了这种方法并尝试减少代码(在这4种情况下),但在其中两种情况下,如果不进入不可导入的上下文,我就无法真正减少代码问题。
答案 0 :(得分:4)
Bar::getValues
移至Foo<Bar>
:
template< typename T >
struct Foo
{
static std::ostream& GetValues_Worker( std::ostream& os, T const& t )
{
// do boost mirror reflection stuff here
return os;
}
std::ostream& getValues( std::ostream& os ) const
{
return GetValues_Worker( os, *static_cast<T const *>(this) );
}
};
此时您可以将两种方法结合起来:
template< typename T >
struct Foo
{
std::ostream& getValues( std::ostream& os ) const
{
T const &t = *static_cast<T const *>(this);
// do boost mirror reflection stuff here
return os;
}
};