2011-05-13 750 views
8

No entiendo por qué esto no se compila:plantilla de clase de plantilla con el parámetro de plantilla const

struct A 
{}; 

template<class T> 
struct B 
{}; 

template<template<class> class T1, class T2> 
struct C 
{}; 

int 
main (int ac, char **av) 
{ 
    typedef B<double> b;    //compiles 
    typedef B<const double> b_const; //compiles 
    typedef B<A> ba;     //compiles 
    typedef B<const A> ba_const;  //compiles 

    typedef C<B,double> c1;   //compiles 
    typedef C<B,const double> c2;  //compiles 
    typedef C<const B,double> c3;  //ISO C++ forbids declaration of ‘type name’ with no type 
} 

(encuentro la referencia a la norma un poco críptica)

¿Qué tengo que cambiar para que se compile?

EDIT:

detalles del compilador (que parece ser relevante):

Using built-in specs. 
Target: x86_64-linux-gnu 
Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 4.4.4-14ubuntu5' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.4 --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --disable-werror --with-arch-32=i686 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu 
Thread model: posix 
gcc version 4.4.5 (Ubuntu/Linaro 4.4.4-14ubuntu5) 

Edit2:

Por medio de explicación, que estoy tratando de hacer algo como esto :

template<template<class> class TheContainer, class T> 
struct Iterator 

template<class T> 
struct Container 

typedef Iterator<Container, double> iterator; 
typedef Iterator<const Container, double> const_iterator; 

La técnica para contenedores sin plantilla se encuentra al final de este documento de actualización: http://www.boost.org/doc/libs/1_46_1/libs/iterator/doc/iterator_facade.html

Creo que la solución no es anidar las plantillas. En retrospectiva, parece obvio.

+0

Esta publicación tiene un tema genial :) – Laserallan

+0

@Laserallan me hace pensar en Perl – Tom

+1

"¿Qué tengo que cambiar para que compile?" Necesitas eliminar el último typedef, obviamente. Más en serio, ¿qué estás tratando de lograr al hacer esto? –

Respuesta

4

El primer argumento para C no es un tipo, por lo tanto, no tiene sentido pasar un tipo const como su arg. Una plantilla no puede ser const o non-const, solo los tipos pueden ser const o non-const. ¿Qué significa const B?

const int tiene sentido. const vector<int> tiene sentido, al igual que vector<const int>. Pero, ¿qué significaría const vector?

(aviso pizca de sal.: Ni siquiera estaba al tanto de plantilla-template-clases antes de ver a esta pregunta)

Para hacer esto más concreto, imaginemos B y C son:

template<class T> 
struct B 
{ 
     T t; 
};  

template<template<class> class T1, class T2> 
struct C 
{ 
     T2 t2; 
     T1<T2> t1; 
}; 

c2 serán de tipo

C<B,const double> 
==> struct { const double t2; T1<const double> t1;} 
==> struct { const double t2; struct { const double b; } t1;} 

qué se puede esperar c3 sea? ¿Que t1 sería en sí mismo const, mientras que t1.b no es const?Supongo que tiene sentido.

+0

Gracias, sí parece obvio ahora. Necesito escribir de forma explícita lo que quiero que hagan las plantillas – Tom

+0

¡Gracias por informarme sobre plantillas de plantillas! –

1

Supongo que B no puede ser constante porque en este momento no tiene un tipo real y el compilador no sabe qué es const. Aparte de dejar el const lejos, no puedo encontrar una solución para compilar correctamente, ya que las plantillas de plantillas son realmente un dolor para el cerebro.

2

Este código exacto se compila en VS2010. No conozco tu compilador pero te sugiero que verifiques en la base de datos de errores del desarrollador del compilador si un error como ese no está registrado.

Lo intentaré en GCC.


Ok GCC (4.5.1) does da el error. Supongo que tendremos que esperar a que alguien con conocimiento estándar sepa si se trata de un comportamiento estándar o un error.


CLANG (2.8) hace da el mismo error (con exactamente el mismo mensaje).

+0

Gracias por probarlo - He publicado mi gcc -v. Voy a echar un vistazo ahora en la base de datos de errores – Tom

+0

No hay problema. Empecé a buscar pero ese mensaje de error se usa en muchos casos donde no puede encontrar el tipo, por lo que es difícil encontrar un error. Creo que tal vez VS2010 es demasiado permisivo también. Difícil de conocer sin conocimiento del estándar. – Klaim

1

Mi apuesta es que MSVC se traga silenciosamente el const de la misma forma que el const classes.

Cuestiones relacionadas