是否存在转发构造函数参数的通用方法?

时间:2013-01-02 12:43:33

标签: c++ templates c++11 constructor clone

我下面有一个有效的Cloneable/CloneableImpl班级对。只要我有从子级到父级的默认构造函数,它就能完成它的工作。

假设Animal的构造函数被修改为Animal( std::string const& name ),需要从子类构造函数传递名称。

如何在保持Cloneable/CloneableImpl通用的同时将此要求纳入结构?

换句话说,我需要能够将Lion,Tiger的所有构造函数参数转发给Animal。有没有办法以通用方式在C ++ 11中执行此操作?

如果不可能,在允许构造函数要求的同时,如何重构这些模板以保持通用?

代码

template<typename P>
struct Cloneable
{
    virtual P* clone() const = 0;
};

template<typename T,typename P>
struct CloneableImpl :
    public P
{
    virtual P* clone() const 
    {
        return new T( dynamic_cast<T const&>(*this));
    }
};

// ----------------------------------------------------------------------------

struct Animal :
    public Cloneable<Animal>
{ 
};

struct Lion  : 
    public CloneableImpl<Lion,Animal> 
{ 
};

struct Tiger : 
    public CloneableImpl<Tiger,Animal> 
{ 
};

int
main( int argv, char* argc[] )
{
    Animal* x = new Lion;
    Animal* y = x->clone();

    // we want to do this without hard-coding in template classes
    // Animal* z = new Lion( "Samba" );  
}

1 个答案:

答案 0 :(得分:9)

关注@ Cheersandhth.-Alf和@R。 Martinho Fernandes在对OP的评论中建议调查完美转发。我研究了一下,想出了这个,这似乎有用。

谢谢你们!

<强> CODE

#include <string>
#include <iostream>

template<typename P>
struct Cloneable
{
    virtual P* clone() const = 0;
};

template<typename T,typename P>
struct CloneableImpl :
    public P
{
    template<typename... Args>
    CloneableImpl( Args&&... args ) 
       : P(std::forward<Args>(args)...)
  {  }

    virtual P* clone() const 
    {
        return new T( dynamic_cast<T const&>(*this));
    }
};

// ----------------------------------------------------------------------------

struct Animal :
    public Cloneable<Animal>
{ 
    Animal( std::string const& name ) : m_name( name ) { }

    std::string  m_name;
};

struct Lion  : 
    public CloneableImpl<Lion,Animal> 
{ 
    template<typename... Args>
    Lion( Args&&... args ) 
       : CloneableImpl<Lion,Animal>(std::forward<Args>(args)...)
  {  }
};

struct Tiger : 
    public CloneableImpl<Tiger,Animal> 
{ 
};

int
main( int argv, char* argc[] )
{
    Animal* x = new Lion( "Samba" );
    Animal* y = x->clone();

    std::cerr << y->m_name << std::endl;
}