Puede alias plantillas (14.5.7) ser explícitamente especializada (14.7.3)?

Mi estándar-fu falla de mí, y no puedo encontrar un compilador para hacer pruebas.

El texto «cuando una plantilla de id se refiere a la especialización de un alias de la plantilla» implica , pero, a continuación, el ejemplo que aparece a referir a algo, lo que implica no.

NB. Estoy trabajando desde n3242, una detrás de la IED, en la que el título de esta sección es «Aliase plantillas». Lol.

  • Para el público en general la información, me gustaría mencionar que sonar soporta alias plantillas.
  • Información de la versión, por favor 🙂
  • Versión SVN, creo.
  • Ah, sí, yo leer que antes de una vez 😉
  • Como este tema es un poco viejo esto puede ser irrelevante, pero alias declaraciones trabajo en gcc 4.7.3.
  • Gracias por la actualización. 😉

4 Comentarios

  1. 26

    Lo que la Norma quiere decir con «especialización» es la transformación de una plantilla genérica para un más especializados entidad. Por ejemplo, crear un no-miembro de la plantilla de clase de los rendimientos de una clase que no es una plantilla de más. El término «especialización» es de dos veces, y puede referirse a un generado la especialización (que es una especialización que se crea una instancia, posiblemente a partir de un parcial de especialización) y a una explícita de especialización (que es lo que usted se refiere).

    Alias plantillas no son una instancia y no hay especializaciones de ellos. No hay nada que ellos pudieran crear instancias para. En cambio, cuando su nombre es seguido por una plantilla de lista de argumentos, el tipo que se denota es el tipo que usted consigue sustituyendo el nombre y la lista de argumentos por el alias ed tipo, la sustitución de todos los parámetros de una plantilla de referencias de los argumentos dados en la lista de argumentos. Es decir, en lugar de la especialización de ser un alias, el alias de la plantilla en sí sirve como un alias, sin la necesidad de crear instancias de nada. Esta sustitución se realiza de forma muy temprana. Considerar:

    template<typename T> using ref = T&;
    template<typename T> void f(ref<T> x) { x = 10; }
    int main() { int a; f(a); return a; /* 10 */ }

    El reemplazo se realiza en el momento ref<T> se denomina (tales nombres que se usan para referirse a la clase o función de la plantilla de especialidades; por lo tanto, la especificación describe tales nombres «que se refieren a la especialización de un alias de plantilla»). Es decir, el parámetro de f tiene el tipo T&, y por lo tanto, T se pueden deducir. Esta propiedad es la prevención explícita o parcial de las especializaciones de alias de plantillas. Porque en el fin de elegir la correcta especialización de ref, necesita saber T. Pero para entenderlo, es necesario comparar ref<T> contra el tipo de argumento para deducir T. Se resumen en el documento N1406, «Propuesta de adición a la de C++: Typedef Plantillas», sección 2.2

    2.2 La Elección Principal: la Especialización frente a Todo lo Demás

    Después de la discusión en los reflectores y en la Evolución WG, resulta que tenemos que elegir entre dos mutuamente exclusivos modelos:

    1. Un typedef de la plantilla no es en sí mismo un alias; sólo el (posiblemente especializados) las instancias de la typedef plantilla son alias. Esta opción nos permite tener la especialización de typedef plantillas.

    2. Un typedef de la plantilla es de por sí un alias; no puede ser especializado. Esta opción permitiría:

      • deducción en typedef plantilla de los parámetros de la función (véase 2.4)
      • una declaración expresa con el uso de typedef plantillas de ser la misma que la declaración sin
        typedef plantillas (véase 2.5)
      • typedef plantillas para que coincida con la plantilla de los parámetros de la plantilla (ver 2.6)

    Cabe señalar que el citado documento, lo que favorece la opción 1, no se encuentra en C++0x.


    EDIT: Debido a que usted quiere desesperadamente tener una especificación de cotización decirlo explícitamente. 14.5p3 es aquel que hace

    Porque un alias de la declaración no puede declarar una plantilla de id, no es posible parcialmente o explícitamente se especializan en un alias de la plantilla.

    • Muy interesante! (Aunque carente de norma explícita de magia!)
    • Wow, esto mata a la mayoría de mis previsto utiliza para la plantilla de alias. Estaba deseando deshacerse de estructuras que sirven para ningún otro propósito que mantener un typedef.
    • Es esto correcto entonces? ¿Uno tiene que retroceder a la edad struct maneras de definir la plantilla de typedef?
    • Sólo si quieres especializarte el typedef. Me di cuenta más tarde, esto no es tan malo-puede tener una plantilla de alias de una plantilla que se ha especializado. Sólo el alias de sí misma no puede ser especializada, que en la práctica no es deseado como a menudo.
  2. 7

    Bjarne dice:

    Especialización obras (puede alias de un conjunto de especializaciones pero no se puede especializar un alias)

    Y, aunque no es una regla explícita, los alias de «plantillas» faltan en la siguiente lista en 14.7.3/1:

    Explícito de especialización de cualquiera de los siguientes:

    • plantilla de función
    • plantilla de clase
    • función miembro de una clase de plantilla
    • miembro de datos estáticos de una clase de plantilla
    • miembro de la clase de una plantilla de clase
    • miembro de la plantilla de clase de una clase o de una clase de plantilla
    • miembro de la plantilla de función de una clase o de una clase de plantilla

    puede ser declarado[…]

    Creo que esta es la mejor garantía de que va a obtener.

    • Atención a publicar algunos de niza ejemplos? Quiero copiar/pegar y poner a prueba a algunos de los compiladores. Creo GCC 4.4 no tiene apoyo en todo, y yo no sé 4.6.1 ahora…
    • Nunca me llegó a hacer ninguna. 🙂
    • template <typename T, int N> struct A { static const int value = N; }; template <typename T> using V = A<T, 42>; template <> using V<int> = A<42, 48>; int main() { std::cout << V<char>::value << ", " << V<int>::value; }, Supongo.
    • Lamentablemente no hay soporte para la plantilla de alias incluso en GCC 4.6.1 🙁
    • Geret’kal : Su código y clang tronco : «error : explícita la especialización de los alias de las plantillas no está permitido»
    • Ja, gracias 😉 Que sería un bonito respuesta con autoridad…
    • la próxima vez que usted podría querer añadir más explicación de por qué actualizado el enlace al sugerir una edición así. Fue una válida editar, pero casi me la rechazaron porque parecía que estaban cambiando el enlace completo a un sitio diferente, por ninguna razón

  3. 4

    No estoy seguro si entiendo la pregunta, pero en cualquier caso he intentado simular la especialización de los alias de la plantilla.

    Supongo que la idea es restringir el alias de la plantilla a determinadas (patrón emparejado tipo); algo que solíamos hacer con este tipo de código:

    template<class Vector> struct old_style;
    template<class T> struct old_style<std::vector<T> >{
       typedef typename std::vector<T>::value_type type;
    };

    (este es sólo un ejemplo, hay otra forma de extraer la value_type de un genérico std::vector).

    Ahora a los alias:

    template<class Vector> using new_style = typename Vector::value_type;

    Lo hace el mismo trabajo, pero esto no sustituye old_stype<...>::type, ya que no es tan restrictiva. El primer intento de tener un perfecto reemplazo de alias es este hipotético código:

    //template<class Vector> using new_style2; //error already here
    //template<class T> using new_style2<std::vector<T> > = typename Vector::value_type;

    Que desgraciadamente no compilar (en teoría, porque nominal de las razones expuestas en otras respuestas y en la norma, en la práctica supongo que no hay ninguna razón fundamental para que esto sea una limitación). Afortunadamente uno puede retroceder a la antigua usanza struct::type forma de hacerlo de un sólo uso el nuevo alias de la plantilla de función para avanzar el trabajo,

    template<class Vector> struct new_style2_aux;
    template<class T> struct new_style2_aux<std::vector<T> >{
       typedef typename std::vector<T>::value_type type;
    };
    template<class Vector> using new_style2 = typename new_style2_aux<Vector>::type;

    Uno puede hacer de modo automático, con un define

    #define SPECIALIZED_ALIAS_TEMPLATE(NamE, Pattern_arG, PatterN_expR, DefinitioN) \
    template<class> struct NamE ## _aux; \
    template<Pattern_arG> struct NamE ## _aux<PatterN_expR>{ \
        typedef DefinitioN type; \
    }; \
    template<class NamE ## _dummy> using NamE = typename NamE ## _aux< NamE ## _dummy >::type; 

    Que puede ser utilizado como:

    SPECIALIZED_ALIAS_TEMPLATE(new_style3, class T, std::vector<T>, typename std::vector<T>::value_type);

    Si uno tiene un número arbitrario de especializaciones (o no locales en el código), uno tiene que usar una más complicado define en dos partes, una para el declarante y otro para que se especializa (como debe ser):

    #define DECLARE_ALIAS_TEMPLATE(NamE)\
    template<class> struct NamE ## _aux;\
    template<class NamE ## _dummy> using NamE = typename NamE ## _aux< NamE ## _dummy >::type; 
    
    #define SPECIALIZE_ALIAS_TEMPLATE(NamE, Pattern_arG, PatterN_expR, DefinitioN)\
    template<Pattern_arG> struct NamE ## _aux<PatterN_expR>{ \
        typedef DefinitioN type; \
    };

    Utiliza de la siguiente manera:

    DECLARE_ALIAS_TEMPLATE(new_style4);
    
    SPECIALIZE_ALIAS_TEMPLATE(new_style4, class T, std::vector<T>, typename std::vector<T>::value_type);
    SPECIALIZE_ALIAS_TEMPLATE(new_style4, class T, std::set<T>, typename std::set<T>::value_type);

    Todo el código anterior puede ser copiado y pegado de la prueba:

    #include<vector>
    #include<map>
    //... paste code above //
    int main(){
        old_style<std::vector<double> >::type a; //is a double
    // old_style<std::set<double> >::type a; //error (should work only for std::vector)
        new_style2<std::vector<double> > b; //is double
    // new_style2<std::set<double> > c; //error (should work only for std::vector)
        new_style3<std::vector<double> > d; //is double
    // new_style3<std::set<double> > d; //error (should work only for std::vector)
        new_style4<std::vector<double> > e; //is double
        new_style4<std::set<double> > f; //is double, this is another specialization
        return 0;
    }

    Lo siento si esto no es lo que usted está buscando. Creo que puede ser utilizado con variadic plantillas, y con más argumentos de plantilla (en la especialización), pero no prueba.

    Mejoras son muy bienvenidos.

    • Ja, +1 cos esto está muy bien. Es, en definitiva, sólo un preprocesador de contenedor para la especialidad de structs, aunque.
    • sí, pero no hay ::type al final de el nombre de alias.
  4. 3

    Si usted necesita pointwise mapeo de algo a los tipos, esto funciona(en gcc 4.8.3):

    // int to type mapper
    template<int BITS>
    struct BitsToTypesMap
    {
        typedef void TYPE;  // default
    };
    
    // pointwise mapping 
    template<>
    struct BitsToTypesMap<32>{  typedef int TYPE;   };
    template<>
    struct BitsToTypesMap<8>{   typedef char TYPE;  };
    template<>
    struct BitsToTypesMap<16>{  typedef short TYPE; };
    
    // cute wrapping
    template<int BITS> using MyScalarType = typename BitsToTypesMap<BITS>::TYPE;
    
    // TEST
    template<int BITS>
    MyScalarType<BITS>
    Add ( MyScalarType<BITS> x, MyScalarType<BITS> y )
    {
        return x+y;
    }
    
    int
    test()
    {
        MyScalarType<32> i=Add<32>(1,2);
        MyScalarType<8 > b=Add<8 >(1,2);
        MyScalarType<16> s=Add<16>(1,2);
        return i+b+s;
    }

Dejar respuesta

Please enter your comment!
Please enter your name here