Especialización de plantillas anidadas

Tener un cerebro pedo … ¿Es posible hacer algo como este trabajo?

template struct Foo { template struct Bar; }; template struct Foo::Bar //Trying to specialize Bar { }; 

No tengo que hacer esto, pero me permitirá ocultar algunos detalles de implementación del ámbito del espacio de nombres.

Sugerencias apreciadas!

PD: olvidé mencionar que el lenguaje no admite explícitamente la especialización para Bar dentro del scope de Foo. AFAICS, de todos modos.

Sí tu puedes. Pero necesitarás cambiar la estructura de la llamada, pero solo un poco.

Específicamente, use el patrón de estrategia para reestructurar la implementación de la función miembro como una clase (lo que permite que se especialice).

Esto está permitido siempre y cuando la clase de estrategia no esté anidada (y, por lo tanto, no dependa del tipo de plantilla no especializada).

por ejemplo (esto probablemente no es sintácticamente correcto, pero la idea debería ser clara)

 template  class OuterThingThatIsNotSpecialized { template  void memberWeWantToSpecialize(const U& someObj_) { SpecializedStrategy::doStuff(someObj_); } }; template  struct SpecializedStrategy; template <> SpecializedStrategy { void doStuff(const int&) { // int impl } }; template <> SpecializedStrategy { void doStuff(const SomeOtherType&) { // SOT impl } }; 

Esto es increíblemente útil porque las llamadas a OuterThingThatIsNotSpecialized para tipos donde no existe una implementación simplemente no se comstackrán.

PD. Incluso puede utilizar esta estrategia para especializar parcialmente las funciones de plantilla, algo que de otra forma es una imposibilidad de C ++.

La cláusula 18, sección 14.7.3 de la norma de 1998 (ISO14882: 1998) dice que no se permite la especialización explícita de las clases de miembros de plantilla (interna) cuando la clase de plantilla (externa) no está explícitamente especializada.

Según estos posts:

http://www.cpptalk.net/template-member-function-specialization-vt11666.html

no puede especializar miembros de plantilla de una clase de plantilla sin especializar la clase externa. No citan verso y capitulo. Mi copia de “The C ++ Programming Language” no revela nada de inmediato, y mi copia de la norma está en casa (mi copia de seguridad, más conocida aquí como “Chris” tampoco está disponible 🙂

No puedes hacer eso. He probado muchas variaciones. Esto , sin embargo, comstack en GCC 4.1:

 template struct Foo { template struct Bar; template<1> struct Bar; }; 

Editar (después de revisar el estándar): Sin embargo, si se da una, puede hacer esto:

 template <> template <> Foo<1> Bar<1>; 

Pero no si Foo no está primero especializado.

Como explicaron los carteles anteriores, esto no es posible. Sin embargo, puede mover la plantilla anidada a una clase base sin plantilla:

 struct FooBase { template struct Bar; } template struct Foo : public FooBase { }; struct FooBase::Bar<1> // specializing Bar { }; 

Como han señalado otros, C ++ no le permite especializar una clase anidada si la plantilla de la clase externa no es también especializada. Cuando tuve una situación como esa, pude resolverla con una clase de ayudante escondida en un espacio de nombres interno:

 namespace internal { template  struct FooBarHelper { /* ... */ }; // Specialization template  struct FooBarHelper { /* specialized version goes here */ }; } template struct Foo { template struct Bar : public internal::FooBarHelper; }; 

Por supuesto, no es tan oculto como le gustaría que fuera.