c++ templates c++11 clang crtp

c++ - clang++ no acepta el uso del parámetro de plantilla de plantilla cuando usa CRTP



templates c++11 (1)

Recibo errores de compilación al intentar llamar al constructor de la clase base en la lista de inicialización derivada al usar un parámetro de plantilla de plantilla con CRTP.

El problema se puede replicar con este fragmento de código:

template <template<class> class Derived, class T> struct base { }; template <class T> struct derived : public base<derived, T> { derived() : base<derived, T>() { } };

El mensaje de error ofensivo:

bug.cpp:10:16: error: template argument for template template parameter must be a class template or type alias template : base<derived, T>() ^ bug.cpp:10:11: error: expected class member or base class name : base<derived, T>() ^ bug.cpp:10:11: error: expected ''{'' or '','' 3 errors generated.

Este problema solo parece ocurrir en clang (3.4), no en g ++ (4.8, 4.7, 4.6). Estoy compilando con -std = c ++ 11 también.

Esta es la primera vez que necesito usar CRTP con el parámetro de plantilla de plantilla. ¿Estoy haciendo esto bien y es un problema con clang ++ o no?

¡He llegado a confiar en los mensajes de error de Clang ++ más que g ++ últimamente!


Su código es legal.

De la norma C ++ 11, sección 14.6.1:

Al igual que las clases normales (sin plantilla), las plantillas de clase tienen un nombre de clase inyectado (Cláusula 9). El nombre de clase inyectada se puede utilizar como nombre de plantilla o nombre de tipo. Cuando se usa con una plantilla-lista-argumentos, como una plantilla-argumento para una plantilla plantilla-parámetro , o como el identi fi cador final en el especi fi cado de tipo elaborado de una declaración de plantilla de clase amiga, se refiere a la propia plantilla de clase. .

Parece que tu versión de clang todavía está implementando la regla anterior. Según sus comentarios adicionales, puede que lo esté haciendo solo en la lista de inicializadores de ctor .

El usuario David Rodríguez - dribeas proporcionó una solución para los compiladores que no han implementado completamente la regla de nombre de clase inyectada C ++ 11. Use cualquier nombre de la clase que no esté no calificado, por ejemplo:

derived() : base< ::derived, T >() // ^^ qualified with global namespace { }

Algunos compiladores pueden requerir esto en la lista de herencia también:

template <class T> struct derived : public base< ::derived, T > // ^^