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