No type named 'type' in CTRP derived class

后端 未结 4 571
猫巷女王i
猫巷女王i 2020-12-31 11:22

I\'ve been experimenting with the Curiously Recurring Template Pattern for a generic single-argument functor and have two implementations: one using a template template para

4条回答
  •  暖寄归人
    2020-12-31 12:03

    Note: This question has already been answered by @r-sahu, but I'd like to elaborate on this and address clang's output specifically.

    The problem can be demonstrated on a much smaller code sample: (@vtt suggested something similar)

    template 
    struct A {
        using _C = typename _CRTP::C;
    };
    
    struct B : public A {
        using C = int;
    };
    

    Compiling that with clang will result in completely misleading error message: (godbolt)

    :3:32: error: no type named 'C' in 'B'
        using _C = typename _CRTP::C;
                   ~~~~~~~~~~~~~~~~^
    :6:19: note: in instantiation of template class 'A' requested here
    struct B : public A {
                      ^
    1 error generated.
    

    GCC's error message is a little more helpful: (godbolt)

    : In instantiation of 'struct A':
    :6:19:   required from here
    :3:33: error: invalid use of incomplete type 'struct B'
        3 |     using _C = typename _CRTP::C;
          |                                 ^
    :6:8: note: forward declaration of 'struct B'
        6 | struct B : public A {
          |        ^
    

    As suggested in the accepted answer, implementing a trait type fixes the issue:

    // this declaration must appear before the definition of A
    template 
    struct a_traits;
    
    template 
    struct A {
        // `a_traits<_CRTP>::type` is an incomplete type at this point,
        // but that doesn't matter since `A` is also incomplete
        using _C = typename a_traits<_CRTP>::type;
    };
    
    // this specialization must appear before the definition of B
    template <>
    struct a_traits { // adding the type specifier `struct` will declare B
        using type = int;
    };
    
    // specifying the template parameter will complete the type `A`, which works since
    // `a_traits` is already complete at this point
    struct B : public A {
        using C = int;
    };
    

提交回复
热议问题