Contenedores de biblioteca estándar con parámetros de plantilla opcionales adicionales?

Después de leer el reclamo varias veces en los artículos, quiero agregar esta pregunta a Stackoverflow y preguntarle a la comunidad, ¿el siguiente código es portátil?

template<template class C> void f() { /* some code goes here ... */ } int main() { f(); } 

¿La implementación que proporciona std::vector realmente permite tener parámetros de plantilla adicionales y por defecto más allá de los dos 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 de este artículo para ver un ejemplo de dicho reclamo.

Encontré el siguiente informe de problema , que dice

No hay 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 implica los parámetros de la 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.

Increíblemente, hace poco que estaba leyendo “Plantillas C ++: la guía completa” y el último libro marcó lo siguiente en la página 111:

Un argumento de plantilla de plantilla debe ser una plantilla de clase con parámetros que coincidan exactamente con los parámetros del 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 del mundo real, compilé lo siguiente en g ++ (exitosamente) y Visual Studio 2008 (error en los parámetros no coincidentes):

 template class MyClass { public: T1 v1; T2 v2; T3 v3; }; template class C> void f() { C *c = new C(); } int main () { f(); return 0; } 

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 que toma argumentos adicionales por defecto”, pero 17.4.4.4/2 permite explícitamente reemplazar las firmas de funciones miembro descritas por otras más largas, siempre que los parámetros adicionales tener valores predeterminados

Sin embargo, no hay una 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.

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ó utilizar cosas como los tipos de asignadores con esteroides (algo así como my_fancy_thing , mientras que std::allocator seguiría funcionando, también). Pero incluso esto mantendría funcionando tu f() , y eso es lo más parecido a una implementación que rompe tu 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 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 decidí no preocuparme por eso.