【问题标题】:Curiously recurring template - variation奇怪地重复出现的模板 - 变体
【发布时间】:2012-04-29 18:12:36
【问题描述】:

关于CRP,如果我想实现它的细微变化(使用模板模板参数)我得到一个编译错误:

template <template <typename T> class Derived>
class Base
{
public:
    void CallDerived()
    {
        Derived* pT = static_cast<Derived*> (this);
        pT->Action(); // instantiation invocation error here
    }
};

template<typename T>
class Derived: public Base<Derived>
{
public:
    void Action()
    {
    }
};

我不太确定有人会选择这种形式(它不会为我编译)而不是使用它(这可行)

template <typename Derived>
class Base
{
public:
    void CallDerived()
    {
        Derived* pT = static_cast<Derived*> (this);
        pT->Action();
    }
};

template<typename T>
class Derived: public Base<Derived<T>>
{
public:
    void Action()
    {
    }
};

【问题讨论】:

    标签: c++ templates crtp


    【解决方案1】:

    这也应该编译。我们只需要明确指定的另一个模板参数

     template <typename T, template <typename T> class Derived>
     class Base
     {
     public:
         void CallDerived()
         {
            Derived<T>* pT = static_cast<Derived<T>*> (this);
            pT->Action(); // instantiation invocation error here
         }
     };
    
    template<typename T>
    class Derived: public Base<T,Derived>
    {
    public:
        void Action()
        {
        }
    };
    

    【讨论】:

    • 非常有趣的一个必须在声明中明确两次声明类型名 T ......不太明白为什么
    • 刚刚意识到派生也必须传输它的T参数。
    【解决方案2】:

    在第一个示例中,类模板实际上采用 模板模板参数,而不仅仅是 模板参数,正如您所写的:

    template <template <typename T> class Derived>
    class Base
    {
         //..
    };
    

    所以这段代码没有意义:

    Derived* pT = static_cast<Derived*> (this);
    pT->Action(); // instantiation invocation error here
    

    这里Derived 是一个模板模板参数,它需要你没有提供给它的模板参数。事实上,在CallDerived() 函数中,您无法知道您需要提供给它的类型,以便执行您打算执行的操作。

    第二种方法是正确的解决方案。使用它。

    【讨论】:

    • 但是在第一种情况下如何提供模板参数.. 使用派生 * pt 也不起作用
    • @Ghita: T 在基类中是未知的。其他解决方案解释了如何将T 传递给基础。但这不是必需的,因为您应该选择第二种解决方案。
    • 基类中有时需要 T。例如。当有成员 T Action(); 当然,您可以使用为每个派生类提供 T 的特征类,但有时您希望 T 和派生独立变化。在这种情况下,您需要带有模板 + 模板模板参数的 [first] 方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多