如何重构这个类模板以最小化锅炉板代码

how to refactor this class template to minimize boiler-plate code?

本文关键字:最小化 代码 何重构 重构      更新时间:2023-10-16

我最近开始使用boost mirror进行ORM反射,这样我就可以最大限度地减少与DB相关的锅炉板代码的数量。

下面列出了我遇到的一种模式。

由于即使对于BazBar的代码看起来也是一样的,我想知道,有可能进一步折叠这个代码吗

如果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下面的答案在大多数情况下都有效。在我的具体情况下,我根据我的真实代码调整了他的解决方案,在四分之二的情况下都有效。在两个失败的案例中,它有点超出了我上面给出的米老鼠例子的范围。我能在SO中找到的解释编译时错误的最接近的解释可能是这篇文章。问题的关键似乎与Worker代码中发生的事情有关。在这两个失败的案例中,我根据从运行时反射得到的结果对子类的成员进行输出流式处理,结果是提升镜像。我认为这是不可推导上下文的情况。我仍然不明白为什么这两个失败案例中的解决方案能准确工作(为什么以虚拟方法的形式使用访问者可以绕过这个问题)。无论如何,我偶然发现了这种方法,并试图进一步减少代码(在这4种情况下),但在其中两种情况下,如果不遇到不可推导上下文问题,我就无法真正减少代码。

Bar::getValues可以使用CRTP下变频移动到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;
}
};