Home > Blockchain >  Recursive class template and implicit instantiation error in C
Recursive class template and implicit instantiation error in C

Time:01-07

The following minimal reproducible example contains a template struct B with default argument type containing a lambda A<[]{ return 1; }>, B is recursively inherited from B<>. And there is a specialization of B for any A<z>.

template<auto>
struct A{};

template<class = A<[]{ return 1; }>>
struct B : B<> {};

template<auto z>
struct B<A<z>> {};

B<int> x;

GCC is ok with the example, by Clang complains:

error: implicit instantiation of template 'B<A<{}>>' within its own definition

Demo: https://gcc.godbolt.org/z/xzjzo7dE9

Which compiler is right here?

P.S. If one modifies the definition of B this way:

template<class>
struct B : B<A<[]{ return 1; }>> {};

then all compilers become totally happy, demo: https://gcc.godbolt.org/z/roqnc39eq

CodePudding user response:

Which compiler is right here?

Both are, since B is ill-formed; NDR. As always, [temp.res]/8 applies:

The validity of a template may be checked prior to any instantiation. The program is ill-formed, no diagnostic required, if:

(8.4) - a hypothetical instantiation of a template immediately following its definition would be ill-formed due to a construct that does not depend on a template parameter, or

The template is B, and "its" definition here speaks of the primary. If we were to instantiate B<> immediately after, we'll get an unconditionally ill-formed class definition. Hence, GCC and Clang can do whatever.

Btw, this entire lambda as a template argument business is a red herring. We can go for plain, old int as parameter and get similar divergence as well.

template<int>
struct A{};

template<class = A<0>>
struct B : B<> {};

template<int z>
struct B<A<z>> {};

B<int> x;

int main() {}

Clang still complains, but now so does GCC.

  •  Tags:  
  • Related