您需要让您的克隆“中间人”类转发构造函数参数,或者更好(Luc Danton 建议这样做)使用 C++11 构造函数继承。
因此,在 C++11 中很容易做到这一点,但在 C++03 中或使用尚不支持 C++11 参数转发或构造函数继承的当前编译器(例如 Visual C++)时就不是那么容易了10.
在 C++03 中使用辅助参数转发器类实现此目的的一种方法在我的旧博客文章“混合通用克隆实现的 3 种方法”中进行了讨论。那么中间人(克隆实现)类可以如下所示:
template< class Derived, class Base >
class WithCloningOf
: public progrock::cppx::ConstructorArgForwarder< Base >
{
protected:
virtual WithCloningOf* virtualClone() const
{
return new Derived( *static_cast< Derived const* >( this ) );
}
public:
template< class ArgPack >
WithCloningOf( ArgPack const& args )
: progrock::cppx::ConstructorArgForwarder< Base >( args )
{}
std::auto_ptr< Derived > clone() const
{
return std::auto_ptr< Derived >(
static_cast< Derived* >( virtualClone() )
);
}
};
ConstructorArgForwarder
我在之前的博文中讨论了 C++03 兼容;它看起来像这样:
template< typename Type >
class ConstructorArgForwarder
: public Type
{
public:
typedef Type Base;
// TODO: remove
virtual ~ConstructorArgForwarder() {}
ConstructorArgForwarder( EmptyArgPack const& )
: Base()
{}
template< class T01 >
ConstructorArgForwarder(
ArgPack< T01 > const& args
)
: Base( args.a01 )
{}
template< class T01, class T02 >
ConstructorArgForwarder(
ArgPack< T01, T02 > const& args
)
: Base( args.a01, args.a02 )
{}
template< class T01, class T02, class T03 >
ConstructorArgForwarder(
ArgPack< T01, T02, T03 > const& args
)
: Base( args.a01, args.a02, args.a03 )
{}
// And more, up to max 12 arguments.
};
它反过来使用一个参数包类ArgPack
(好吧,类模板),它看起来像这样:
enum NoArg {};
template<
class T01 = NoArg, class T02 = NoArg, class T03 = NoArg,
class T04 = NoArg, class T05 = NoArg, class T06 = NoArg,
class T07 = NoArg, class T08 = NoArg, class T09 = NoArg,
class T10 = NoArg, class T11 = NoArg, class T12 = NoArg
>
struct ArgPack;
template<
>
struct ArgPack<
NoArg, NoArg, NoArg, NoArg, NoArg, NoArg,
NoArg, NoArg, NoArg, NoArg, NoArg, NoArg
>
{};
typedef ArgPack<
NoArg, NoArg, NoArg, NoArg, NoArg, NoArg,
NoArg, NoArg, NoArg, NoArg, NoArg, NoArg
> EmptyArgPack;
inline ArgPack<> args() { return ArgPack<>(); }
template<
class T01
>
struct ArgPack<
T01, NoArg, NoArg, NoArg, NoArg, NoArg,
NoArg, NoArg, NoArg, NoArg, NoArg, NoArg
>
{
T01 const& a01;
ArgPack( T01 const& v01 )
: a01( v01 )
{}
};
template< class T01 >
inline ArgPack< T01 >
args( T01 const& a01 )
{
return ArgPack< T01 >( a01 );
}
免责声明:错误可能只是偷偷溜进来,例如从我的博客中复制代码。但是,它在我于 2010 年 5 月发布时起作用。
注意:正如我在上述两篇博文中的最后一篇关于克隆的讨论,有三种主要的通用方法可以做到这一点,其中对于 C++03,简单的宏以良好的优势击败其他两种。但是,对于 C++11,您在此处选择的“中间人”方法似乎更好。通过支配的“横向继承”既复杂又低效,但如果你仅限于 C++03,那么请考虑一个简单的宏!
注 2:上一次我建议做实际和明智的事情时,我被严重否决(大概是 Reddit 的孩子们)。然而,从那以后,我不再关心 SO 代表点数,尤其是反对票。所以,很高兴,我现在可以再次给出很好的建议,就像在过去的 Usenet 时代一样,只是无视那些不赞成投票的孩子对某些词的盲目反应。:-)