【问题标题】:How to use a nested typedef in a template?如何在模板中使用嵌套的 typedef?
【发布时间】:2015-03-12 16:14:55
【问题描述】:

我想从模板类型Base 派生一个类型Test,我专门研究派生类型(即Base<Test>)。

在模板化类型中,我想使用派生类型(模板参数)中定义的 typedef。

但是,我得到这个编译错误:

error C2039: 'X' : is not a member of 'Test'

这里是sn-p的代码:

template <typename T>
class Base
{
protected:
  void func(typename T::X x) {}
};


class Test : public Base<Test>
{
public:
  typedef int X;
};

这可行吗?如果可行,我需要解决什么问题?

(我看到了针对此类问题的几个答案,但看起来我的场景并没有通过为 typename 加上前缀来解决 - 这与从专用于派生类型的模板派生有关吗?)

【问题讨论】:

    标签: c++ templates


    【解决方案1】:

    除了 typedef,您还可以将类型声明为基类中的第二个模板参数:

    template <typename T, typename X>
    class Base
    {
    protected:
      void func(X x) {}
    };
    
    
    class Test : public Base<Test, int>
    {
    public:
    //  typedef int X;
    };
    

    【讨论】:

    • 我喜欢这样。加一,欢迎来到 Stack Overflow。
    • 虽然不是最纯粹的CRTP。
    【解决方案2】:

    你有一个循环,不能用前向声明来解决。但这会起作用,尽管(我怀疑)没有像你想要的那样严格定义。

    template <typename T>
    class Base
    {
    protected:
        template<typename Y>
        void func(Y x) {}
    };
    
    class Test : public Base<Test>
    {
    public:
        typedef int X;
    };
    

    如果func 是公开的,那么你可以写

    Test t;
    Test::X x;
    t.func(x)
    

    这对于我想到的好奇重复模板模式的任何使用都是令人满意的。

    【讨论】:

    • 这适用于我上面的示例演示代码,但我认为它不适用于我尝试编译的更复杂的实际代码:)
    【解决方案3】:

    这对我有用:

    template <typename T> struct Traits;
    
    template <typename Derived>
    class Base
    {
       protected:
          void func(typename Traits<Derived>::X x) {}
    };
    
    
    class Test;
    
    template <> struct Traits<Test>
    {
      typedef int X;
    };
    
    
    class Test : public Base<Test>
    {
    };
    

    【讨论】:

    • 我认为你应该这样做——我想这有点像提取接口以避免两种类型之间的循环引用。
    【解决方案4】:

    我不确定这种行为,也许有人可以澄清一下。但据我所知,当您执行 : public Base&lt;Test&gt; 时,类型名称 X 不存在(因为在下面声明)。

    如果您在进行继承之前创建了一个包装类,则在您进行继承时该类型将存在,并且模板实例化将起作用。

    使用 VC++ 2013 编译

    template <typename T>
    class Base
    {
    protected:
        void func(typename T::X x) {}
    };
    
    
    class TestWrapper
    {
    public:
        typedef int X; //Declared, now it exists for the compiler
    };
    
    class Test
        :public Base<TestWrapper> //Compiles correctly
    {
    
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-09
      • 1970-01-01
      • 2012-06-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多