c++ - ¿Por qué un parámetro de plantilla de plantilla no permite ''typename'' después de la lista de parámetros?
templates c++11 (2)
Plantilla de plantilla typename?
Cuando se usa la sintaxis de la plantilla de la plantilla como en la template <template <typename> class T>
, se requiere el uso de la class
palabra clave, ya que el uso de typename
un error en la línea de:
error: el parámetro de plantilla de plantilla requiere ''clase'' después de la lista de parámetros
En todas partes, las palabras clave typename
y class
son intercambiables en el caso básico de declarar un parámetro de plantilla.
Podría argumentar que el requisito al usar plantilla de plantilla es una pista de que se espera que pase un tipo de clase , pero este no es siempre el caso (especialmente no después de que C ++ 11 introdujo alias de tipo de plantilla).
template <template <typename> class T> // ''class'' keyword required.
struct Foo {
using type = T<int>;
};
template <typename T>
using type = T (*)();
using func_ptr_t = Foo<type>::type;
¿Cuál es el razonamiento detrás de esto?
- ¿Hay alguna razón específica sobre por qué
typename
no está permitido en las declaraciones de plantillas? - ¿El estándar de C ++ dice algo sobre esto?
Estoy buscando el racional detrás de esta restricción [...]
Antes de que se introdujera C ++ 11, las únicas plantillas que se podían pasar a un parámetro de plantilla de plantilla eran las plantillas de clase . Es por eso que el uso de la class
palabras clave se hizo cumplir. Además, la palabra clave typename
implica que el parámetro de la plantilla es una sustitución para un tipo arbitrario y no una plantilla , por lo que usar typename
en ese contexto simplemente difuminaría la línea entre los nombres de los tipos y las plantillas (de clase ). Eso es comprensible
Hoy en día, tales argumentos pueden ser los nombres de plantillas de clases o plantillas de alias , y dado que estos ni siquiera están conectados remotamente, la aplicación de la class
palabras clave es más o menos obsoleta. La propuesta N4051 opta por cambiar esto con C ++ 1Z.
Respuesta corta : porque el estándar así lo dice .
Respuesta más larga : antes de la estandarización, las plantillas de C ++ requerían la palabra clave class
para todos los parámetros de la plantilla. Sin embargo, para enfatizar el hecho de que las plantillas también podrían ser de tipo no de clase (es decir, incorporado), se introdujo una palabra clave alternativa typename
. Sin embargo, en C ++ 98, los parámetros plantilla-plantilla solo podían ser del tipo clase, y esta fue la razón por la cual la palabra clave typename
no se agregó en ese contexto.
Introduzca C ++ 11 y sus nuevos alias de plantilla de características, que ahora también introdujeron plantillas que no son de clase y, por lo tanto, parámetros de plantilla de plantilla que no son de clase:
template<typename T> struct A {};
template<typename T> using B = int;
template<template<typename> class X> struct C;
C<A> ca; // ok
C<B> cb; // ok, not a class template
template<template<typename> typename X> struct D; // error, cannot use typename here
El ejemplo anterior se tomó de la propuesta actual N4051 de C ++ 1z titulada Permitir typename
en un parámetro de plantilla de plantilla , y propone permitir precisamente eso.
Clang 3.5 SVN ahora es compatible con el -std=c++1z
.