2009-09-24 20 views
24

Después de haber leído el reclamo varias veces en los artículos - Quiero agregar esta pregunta a Stackoverflow, y preguntar a la comunidad - ¿el siguiente código es portátil?Contenedores de biblioteca estándar con parámetros de plantilla opcionales adicionales?

template<template<typename T, typename Alloc> class C> 
void f() { 
    /* some code goes here ... */ 
} 

int main() { 
    f<std::vector>(); 
} 

es la implementación que suministra std::vector realmente permite tener parámetros de plantilla adicionales, en mora más allá de los dos bien conocidos? Esto haría que el código anterior esté mal formado, ya que asume dos parámetros de plantilla. Consulte el último párrafo in this article para obtener un ejemplo de dicho reclamo.

Respuesta

22

encontré la siguiente issue report, que dice

No hay ninguna ambigüedad; el estándar es claro como está escrito. Los implementadores de la biblioteca no pueden agregar parámetros de plantilla a las clases de biblioteca estándar. Esto no cae dentro de la regla "como si", por lo que solo se permitiría si el estándar otorgara una licencia explícita para que los implementadores lo hicieran. Esto requeriría un cambio en el estándar.

El LWG decidió no realizar este cambio, ya que rompería el código de usuario que implicaba los parámetros de plantilla de plantilla o las especializaciones de las plantillas de clase de biblioteca estándar.

Los libros y las personas que dicen que una implementación puede agregar otros parámetros opcionales parecen estar equivocados.

1

Ver subsubsecciones de 17.4.4 [lib.conforming].

17.4.4.3/3 dice que "una función global o no miembro no puede ser declarada por la implementación como tomando argumentos predeterminados adicionales", pero 17.4.4.4/2 permite explícitamente reemplazar las firmas de funciones miembro descritas por otras más largas como los parámetros adicionales tienen valores predeterminados.

No hay sección para plantillas, así que si sintieron la necesidad de proporcionar 17.4.4.3/3, me parece que los parámetros adicionales de la plantilla están permitidos, salvo que la redacción indique lo contrario.

+0

Ok, no importa - un informe de problema es obviamente mejor que mi suposición: P – me22

0

He visto este reclamo, también. Pero.

Por un lado, nunca he visto una implementación haciendo esto. Me parece recordar que Andrei Alexandrescu alguna vez consideró usar cosas como los tipos de asignadores con esteroides (algo así como my_fancy_thing<std::allocator,more_info_to_pass_to_the_container>, mientras que solo std::allocator seguiría funcionando, también). Pero incluso esto mantendría funcionando su f(), y eso es lo más parecido a una implementación que rompe su ejemplo que alguna vez escuché.

Creo que esto cae más o menos en la misma categoría que la afirmación de que un puntero 0 no necesariamente tiene que estar representado por un valor con todos los bits configurados en cero, incluso si los proveedores realmente tienen esa libertad (que no Lo sé, ya que hay reclamos de ambos lados, también), nunca lo usarán, porque eso rompería básicamente todo el código existente.

Así que hace tiempo que he decidido no preocuparme por ello.

+0

Alguien archivó un problema y una solicitud de extracción para la [impresora bonita] (http://louisdx.github.com/cxx-prettyprint/) una vez en el pretexto de que esos argumentos adicionales realmente aparecieron en su código MSVC y así hice que las especializaciones que proporcioné se rompieran ... :-( –

2

Increíblemente, estaba leyendo recientemente "C plantillas ++: La guía completa", y el último libro marcado el siguiente en la página 111:

Un argumento plantilla plantilla debe ser una plantilla de clase con los parámetros que coinciden exactamente con los parámetros de el parámetro de plantilla de plantilla que sustituye.Los argumentos de plantilla predeterminados de un argumento de plantilla de plantilla se ignoran (pero si el parámetro de plantilla de plantilla tiene argumentos predeterminados, se tienen en cuenta durante la instanciación de la plantilla).

Por lo tanto, si el libro se va a creer, su ejemplo donde se agregan parámetros predeterminados no estándar a std :: vector sería legal, ya que los argumentos de plantilla predeterminados de un argumento de plantilla de plantilla se ignoran.

Como prueba en el mundo real, compilado la siguiente en g ++ (con éxito) y Visual Studio 2008 (no se ajustó en los parámetros no coincidentes):

template<typename T1, typename T2, typename T3 = float> 
class MyClass 
{ 
public: 
    T1 v1; 
    T2 v2; 
    T3 v3; 
}; 

template<template<typename T1, typename T2> class C> 
void f() 
{ 
    C<int,double> *c = new C<int,double>(); 
} 

int main() 
{ 
    f<MyClass>(); 
    return 0; 
} 
+2

Lo que quieren decir con "Los argumentos de plantilla predeterminados de un argumento de plantilla de plantilla son ignorados" es que aunque un parámetro puede tener un argumento predeterminado, ese argumento predeterminado no es usted sed y el parámetro correspondiente cuenta como si no tuviera un argumento predeterminado. Por lo tanto, si el impl tuviera un vector con 3 parámetros, y el tercero tiene un argumento predeterminado, entonces pasar el vector como un argumento de plantilla de plantilla es como si ese argumento predeterminado no estuviera allí. –

+0

Intenté compilar el ejemplo con g ++ 4.4.1 - rechaza, mientras que g ++ 4.1 acepta el código. Parece que fue un error en GCC. –

+0

Gracias por la aclaración sobre ese pasaje, lo estaba interpretando de manera un poco diferente. Me había compilado en 4.1 (una máquina virtual de Fedora más antigua que tenía pateando). – csj

Cuestiones relacionadas