クローン "ミドルマン"クラスの前方コンストラクタ引数、またはより良い(Luc Dantonがこれを示唆した)C++ 11コンストラクタ継承を使用する必要があります。
これをC++ 11で行うのは簡単ですが、C++ 03やC++ 11の引数の転送やコンストラクタの継承をまだサポートしていない現在のコンパイラでは簡単ではありません。 Visual C++ 10。
ヘルパー引数フォワーダクラスを使用してC++ 03で行う方法の1つは、私の古いブログの投稿"3 ways to mix in a generic cloning implementation"で議論されています。そして、仲介(クローニング実装)クラスは次のようになります。
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())
);
}
};
を私は、以前のブログ投稿でC++ 03互換ConstructorArgForwarder
を議論しました。それは次のようになります。
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
(OKだけでなく、クラステンプレート)、使用しています:
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);
}
は免責事項:erorsはちょうど潜入していることを例えば私のブログからコードをコピーする際に。しかし、それについては、2010年5月に投稿した時に働いた。
注:上記の2つのブログの投稿の最後で、クローンについては、3つのの一般的な方法、これらのうち、単純なマクロは、C++ 03の場合、他の2つのマージンを上回ります。しかし、C++ 11では、ここで選択した「仲介者」のアプローチが優れています。優位性を介して "横の継承"は複雑で非効率的ですが、C++ 03に制限されている場合は、単純なマクロを検討してください!
注2:私が実用的な&を知覚することを示唆した最後の時間は、私は大きく(おそらくRedditの子供たちによって)下降していました。しかし、それ以来、私はSOの担当者のポイント、特にダウンボントについて気にすることをやめました。だから、幸いなことに、古いユーズネットの時と同じように、良いアドバイスをやり直すことができます。 :-)
コンパイラエラーとは何ですか? –
AFAIKあなたのコンパイラにはそれがありませんが、継承されたコンストラクタは、この場合可変長の完璧なコンストラクタよりも優先される可能性があります。これは、 'Clonable'定義で' Using Base :: Base; 'のようになります。ヘッドアップと同じように! –