C++ 我可以以某种方式公开模板参数吗?

C++ 我可以以某种方式公开模板参数吗?,c++,templates,clone,crtp,template-templates,C++,Templates,Clone,Crtp,Template Templates,我想为各种类层次结构提供适当的克隆机制。这似乎是一个合理的想法,我使用CRTP拼凑了一个基本解决方案,在派生类中实现必要的clone()函数 我还使用template-template参数将其模板化,以允许策略控制克隆的存储/所有权: template <typename base, typename derived> struct clone_raw { typedef derived * return_type; stati

我想为各种类层次结构提供适当的克隆机制。这似乎是一个合理的想法,我使用CRTP拼凑了一个基本解决方案,在派生类中实现必要的
clone()
函数

我还使用template-template参数将其模板化,以允许策略控制克隆的存储/所有权:

    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

    // 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);
        }
    };
//带有基本CRTP帮助程序的派生类CRTP
模板
类clonable_派生:公共基
{
公众:
//定义派生类的父类
使用parent=clonable\u派生;
//构造函数转发(启用所有构造函数)
使用base::base;
使用policy=base::policy;//???
使用clone_policy=policy;
使用clone\u type=typename clone\u policy::return\u type;
//使用策略克隆
克隆类型克隆()常量覆盖
{
返回克隆策略::克隆(此);
}
};
一切似乎都准备好了,但是我被难住了,不知道如何公开策略模板,以便派生的可克隆类型可以访问该模板,从而为它们的基/派生对实例化适当的策略

使用别名模板:

template <class A, class B>
using policy = typename base::template policy<A,B>;
模板
使用policy=typename base::模板策略;

好的-巴里的答案是正确的-模板别名绝对是正确的工具

我的原始代码中存在各种问题,包括以下问题:除非是协变的,否则无法更改虚拟的返回类型,
unique_ptr
shared_ptr
似乎不支持协变(至少在VC++2015更新3中不支持)

所以,这里是工作代码——我当然愿意接受改进建议

    // cloning policies:
    //  clone_raw       = new
    //  clone_shared    = std::shared<>
    //  clone_unique    = std::unique<>

    template <class base, class derived>
    struct clone_raw
    {
        using return_type = base *;
        static return_type clone(const base * original) { return new derived(static_cast<const derived &>(*original)); }
    };

    template <class base, class derived>
    struct clone_shared
    {
        typedef std::shared_ptr<base> return_type;
        static return_type clone(const base * original) { return std::make_shared<derived>(static_cast<const derived &>(*original)); }
    };

    template <class base, class derived>
    struct clone_unique
    {
        typedef std::unique_ptr<base> return_type;
        static return_type clone(const base * original) { return std::make_unique<derived>(static_cast<const derived &>(*original)); }
    };

    // base class CRTP
    template <class base, template <class, class> typename policy = clone_raw>
    class clonable_base
    {
    public:

        // define our derived's parent class
        using parent = clonable_base<base, policy>;

        template <class derived>
        using policy_alias = policy<base, derived>;

        using clone_policy = policy_alias<base>;
        using clone_type = typename clone_policy::return_type;

        // clone using policy
        virtual clone_type clone() const = 0;
    };

    // 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;

        template <class derived>
        using policy_alias = typename base::template policy_alias<derived>;

        using clone_policy = typename policy_alias<derived>;
        using clone_type = typename clone_policy::return_type;

        // clone using policy
        clone_type clone() const override
        {
            return clone_policy::clone(this);
        }
    };
//克隆策略:
//克隆\原始=新
//克隆共享=标准::共享
//克隆_unique=std::unique
模板
结构克隆
{
使用返回类型=基*;
静态返回类型克隆(const base*original){返回新的派生(static_cast(*original));}
};
模板
结构克隆共享
{
typedef std::共享\u ptr返回\u类型;
静态返回类型克隆(const base*original){return std::make_shared(static_cast(*original));}
};
模板
结构克隆_唯一
{
typedef std::唯一的返回类型;
静态返回类型克隆(const base*original){return std::make_unique(static_cast(*original));}
};
//基类CRTP
模板
类可克隆库
{
公众:
//定义派生类的父类
使用parent=clonable\u base;
模板
使用policy_alias=policy;
使用克隆策略=策略别名;
使用clone\u type=typename clone\u policy::return\u type;
//使用策略克隆
虚拟克隆类型clone()const=0;
};
//具有基本CRTP帮助程序的派生类CRTP
模板
类clonable_派生:公共基
{
公众:
//定义派生类的父类
使用parent=clonable\u派生;
//构造函数转发(启用所有构造函数)
使用base::base;
模板
使用policy\u alias=typename base::template policy\u alias;
使用clone\u policy=typename policy\u别名;
使用clone\u type=typename clone\u policy::return\u type;
//使用策略克隆
克隆类型克隆()常量覆盖
{
返回克隆策略::克隆(此);
}
};
这里有一个简单的测试:

        class Example : public clonable_base<Example, clone_shared>
        {
        public:
            virtual void explain() const = 0;
        };

        class Ex1 : public clonable_derived<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_derived<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;
        };

int main()
{
    Ex1 ex1("example 1");
    Ex2 ex2("example 2", "this is derived derived example");
    auto clone = ex2.clone();

    ex1.explain();
    std::cout << std::endl;
    ex2.explain();
    std::cout << std::endl;
    clone->explain();
    std::cout << std::endl;

    return 0;
}
类示例:公共可克隆\u库
{
公众:
虚空解释()常量=0;
};
类Ex1:公共可克隆的
{
公众:
Ex1(const char*text):m_text(text){}

void explain()const override{std::cout这看起来很有希望。如果我像上面所写的那样使用我的代码,我的头脑目前正在爆炸“重写虚拟函数返回类型不同并且不是协变的”。缺少一些基本的东西。但是谢谢:D
    // cloning policies:
    //  clone_raw       = new
    //  clone_shared    = std::shared<>
    //  clone_unique    = std::unique<>

    template <class base, class derived>
    struct clone_raw
    {
        using return_type = base *;
        static return_type clone(const base * original) { return new derived(static_cast<const derived &>(*original)); }
    };

    template <class base, class derived>
    struct clone_shared
    {
        typedef std::shared_ptr<base> return_type;
        static return_type clone(const base * original) { return std::make_shared<derived>(static_cast<const derived &>(*original)); }
    };

    template <class base, class derived>
    struct clone_unique
    {
        typedef std::unique_ptr<base> return_type;
        static return_type clone(const base * original) { return std::make_unique<derived>(static_cast<const derived &>(*original)); }
    };

    // base class CRTP
    template <class base, template <class, class> typename policy = clone_raw>
    class clonable_base
    {
    public:

        // define our derived's parent class
        using parent = clonable_base<base, policy>;

        template <class derived>
        using policy_alias = policy<base, derived>;

        using clone_policy = policy_alias<base>;
        using clone_type = typename clone_policy::return_type;

        // clone using policy
        virtual clone_type clone() const = 0;
    };

    // 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;

        template <class derived>
        using policy_alias = typename base::template policy_alias<derived>;

        using clone_policy = typename policy_alias<derived>;
        using clone_type = typename clone_policy::return_type;

        // clone using policy
        clone_type clone() const override
        {
            return clone_policy::clone(this);
        }
    };
        class Example : public clonable_base<Example, clone_shared>
        {
        public:
            virtual void explain() const = 0;
        };

        class Ex1 : public clonable_derived<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_derived<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;
        };

int main()
{
    Ex1 ex1("example 1");
    Ex2 ex2("example 2", "this is derived derived example");
    auto clone = ex2.clone();

    ex1.explain();
    std::cout << std::endl;
    ex2.explain();
    std::cout << std::endl;
    clone->explain();
    std::cout << std::endl;

    return 0;
}