c++ templates c++11 language-lawyer typename

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 .