Clase de plantilla recursiva y error de instanciación implícita en C++.
El siguiente ejemplo mínimo reproducible contiene una plantilla “struct B” con un tipo de argumento predeterminado que contiene una lambda “A<[]{ return 1; }>”, “B” se hereda recursivamente de “B<>”. Y hay una especialización de “B” para cualquier “A
template<auto>
struct A{};
template<class = A<[]{ return 1; }>>
struct B : B<> {};
template<auto z>
struct B<A<z>> {};
B<int> x;
GCC está bien con el ejemplo, pero Clang se queja:
error: implicit instantiation of template 'B<A<{}>>' within its own definition
Demo: https://gcc.godbolt.org/z/xzjzo7dE9
¿Qué compilador tiene la razón aquí?
P.S. Si se modifica la definición de "B" de esta manera:
```cpp
template<class>
struct B : B<A<[]{ return 1; }>> {};
entonces todos los compiladores quedan completamente satisfechos, demo: https://gcc.godbolt.org/z/roqnc39eq
davy.ai
El comportamiento en este caso es indefinido según el estándar de C++. La estructura de plantilla
B
se hereda recursivamente deB<>
con un tipo de argumento predeterminado que contiene una lambda. Sin embargo, la especialización deB
para cualquierA<z>
se define antes de que la definición deB
esté completa, por lo tanto, Clang se queja correctamente de esta instancia implícita dentro de su propia definición.La modificación realizada en
B
resuelve este problema mediante la introducción de una herencia no recursiva deB<a<[]{ return="" 1;="" }="">>
. Por lo tanto, todos los compiladores están satisfechos con esta definición modificada deB
.Vale la pena señalar que confiar en un comportamiento indefinido de esta manera puede llevar a resultados inesperados y se debe evitar en el código de producción.</a<[]{>