代码之家  ›  专栏  ›  技术社区  ›  bremen_matt

仅与模板化派生类一起工作的CRTP特性

  •  0
  • bremen_matt  · 技术社区  · 7 年前

    template<typename Derived>
    struct traits;
    
    template<typename Derived>
    struct Base {
        using size_type = typename traits<Derived>::size_type;
    };
    
    template <typename T>
    struct Derived1 : Base<Derived1<T>>{
        using size_type = size_t;
        void print(){ std::cout << "Derived1" << std::endl; }
    };
    
    template <typename T>
    struct traits<Derived1<T>> {
        using size_type = size_t;
    };
    
    int main()
    {
        using T = float;
        Derived1<T> d1;
        d1.print();
    }
    

    我的理解是,这个习语的目的是延迟 Base size_type . 我感到困惑的是,这个模式似乎只在派生类本身被模板化的情况下才起作用。例如,如果我们将代码更改为:

    template<typename Derived>
    struct traits;
    
    template<typename Derived>
    struct Base {
        using size_type = typename traits<Derived>::size_type;
    };
    
    struct Derived1 : Base<Derived1>{
        using size_type = size_t;
        void print(){ std::cout << "Derived1" << std::endl; }
    };
    
    template <>
    struct traits<Derived1> {
        using size_type = size_t;
    };
    
    int main()
    {
        Derived1 d1;
        d1.print();
    }
    

    然后我们得到错误

    prog.cc: In instantiation of 'struct Base<Derived1>':
    prog.cc:21:19:   required from here
    prog.cc:18:58: error: invalid use of incomplete type 'struct traits<Derived1>'
         using size_type = typename traits<Derived>::size_type;
                                                              ^
    prog.cc:14:8: note: declaration of 'struct traits<Derived1>'
     struct traits;
            ^~~~~~
    prog.cc: In function 'int main()':
    prog.cc:33:9: error: 'Derived1' is not a template
             Derived1<float> d1;
    

    0 回复  |  直到 7 年前
        1
  •  1
  •   aep    7 年前

    你看到的问题与CRTP无关。

    以下是标准中提到的。

    如果类模板在实例化时已声明但未定义(13.7.4.1), 实例化产生一个不完整的类类型(6.7)。[示例:

    template<class T> class X; X<char> ch; // error: incomplete type
    X<char>
    

    traits 只在 Base<Derived> ,因此按照标准( ), struct traits<Derived>

    您应该对代码重新排序,以便它看到 traits<Derived> 专业化 基础<派生>

        2
  •  1
  •   Daniel Duvilanski    7 年前

    您看到的编译错误与CRTP无关,它只是依赖关系的一点混乱。

    在没有模板的代码中,您的“Base”结构需要专门的“traits”结构的定义,但它只在之后出现,因此它尝试使用上面声明中看到的不完整类型。

    class Derived1;
    
    template<typename Derived>
    struct traits;
    
    template <>
    struct traits<Derived1> {
        using size_type = size_t;
    };
    
    template<typename Derived>
    struct Base {
        using size_type = typename traits<Derived>::size_type;
    };
    
    struct Derived1 : Base<Derived1>{
        using size_type = size_t;
        void print(){ std::cout << "Derived1" << std::endl; }
    };
    
    
    int main()
    {
        Derived1 d1;
        d1.print();
    }
    
    推荐文章