我想爲各種類層次結構提供適當的克隆機器。看起來像一個合理的想法,我用CRTP拼湊了一個基本的解決方案,以在派生類中實現必要的clone()
函數。可以以某種方式公開模板模板參數嗎?
我再與模板的模板參數模板它允許政策來控制克隆的存儲/持股比例:
template <typename base, typename derived>
struct clone_raw
{
typedef derived * return_type;
static return_type clone(const base * original) { return new derived(static_cast<const derived &>(*original)); }
};
template <typename base, typename derived>
struct clone_shared
{
typedef std::shared_ptr<derived> return_type;
static return_type clone(const base * original) { return std::make_shared<derived>(static_cast<const derived &>(*original)); }
};
template <typename base, typename derived>
struct clone_unique
{
typedef std::unique_ptr<derived> return_type;
static return_type clone(const base * original) { return std::make_unique<derived>(static_cast<const derived &>(*original)); }
};
// derived class CRTP without base CRTP helper
template <typename base, typename derived, template <typename,typename> typename policy = clone_raw>
class clonable : public base
{
public:
// define our derived's parent class
using parent = clonable<base, derived, policy>;
// constructor forwarding (enable all constructors)
using base::base;
// clone using policy
auto clone() const
{
return policy<base, derived>::clone(this);
}
};
這工作得相當好,每一個派生類需要使用CRTP調用以上機器。
class Example
{
public:
virtual std::shared_ptr<Example> clone() const = 0;
virtual void explain() const = 0;
};
class Ex1 : public clonable<Example, Ex1>
{
public:
Ex1(const char * text) : m_text(text) {}
void explain() const override { std::cout << m_text; }
private:
const char * m_text;
};
class Ex2 : public clonable<Ex1, Ex2>
{
public:
Ex2(const char * text, const char * extra) : parent(text), m_extra(extra) {}
void explain() const override { parent::explain(); std::cout << " " << m_extra; }
private:
const char * m_extra;
};
然而,這留下的基類需要實現根虛擬clone()方法,它意味着無處不在的層次結構中的克隆政策必須說明一遍又一遍。這當然是詛咒良好做法/常識/效率/正確性默認/等
所以,我算了一下,怎麼樣我作出這樣的工作,在一起的兩個CRTP模板,一個提供基類初始虛擬clone()
用正確的簽名,然後使用它的父類以確定要使用正確的克隆政策派生CRTP,這樣一個只需要指定策略一次,根類,所有的派生類將實行正確clone()
覆蓋智能地自行確定基類正在使用哪種策略。
不過,我想不通,是如何將策略模板模板暴露於所推導出CRTP模板,使他們不必採取任何明確的政策參數 - 以滿足設計理念。
// base class CRTP
template <typename base, template <typename, typename> typename policy = clone_raw>
class clonable_base : base
{
public:
// define our derived's parent class
using parent = clonable_base<base, policy>;
// constructor forwarding (enable all constructors)
using base::base;
using clone_policy = policy<base, base>;
using clone_type = typename clone_policy::return_type;
// clone using policy
virtual clone_type clone() const = 0
{
return clone_policy::clone(this);
}
};
所以這裏的百萬美元的問題是:我怎麼暴露policy
模板模板下面衍生CRTP:
// derived class CRTP with base CRTP helper
template <typename base, typename derived>
class clonable_derived : public base
{
public:
// define our derived's parent class
using parent = clonable_derived<base, derived>;
// constructor forwarding (enable all constructors)
using base::base;
using policy = base::policy; // ???
using clone_policy = policy<base,derived>;
using clone_type = typename clone_policy::return_type;
// clone using policy
clone_type clone() const override
{
return clone_policy::clone(this);
}
};
一切都似乎是在地方,但我難倒如何暴露策略模板模板使派生可克隆類型可以訪問實例化一個合適的政策,他們的基地/導出對?!
這看起來有希望的。我的頭目前正在爆炸「重寫虛函數返回類型不同並且不是協變」 - 如果我使用上面寫的代碼。缺少一些基本的東西。但是,謝謝:D – Mordachai