2012-03-15 12 views
5

Los argumentos de plantilla predeterminados se pueden usar para simular alias para expresiones de tipo complejo en una declaración de plantilla. Por ejemplo:¿Es posible simular argumentos de plantilla por defecto en especializaciones parciales?

template <typename X, 
      typename Y = do_something_with<X>::type, 
      typename Z = some_other_thing_using<X, Y>::type 
struct foo { ... X, Y, Z ... }; 

Sin embargo, especializaciones parciales no pueden tener argumentos de plantilla por defecto ([C++11: 14.5.5/8]), por lo que este truco no funciona. Es posible que se pregunte por qué un typedef en el cuerpo no funcionaría, y la respuesta es que los alias deben estar en el alcance antes del cuerpo de la clase, para hacer la habilitación condicional; por ejemplo:

template <typename T, typename Enable = void> 
struct bar; 

// Wishful thinking: 
template <typename X, 
      typename Y = do_something_with<X>::type, 
      typename Z = some_other_thing_using<X, Y>::type> 
struct bar <std::vector<X>, 
      typename enable_if< 
       some_condition<X, Y, Z> 
      >::type> 
    { ... }; 

La forma en que he trabajado alrededor de ella está utilizando un tipo de auxiliares:

template <typename X> 
struct bar_enabled { 
    typedef typename do_something_with<X>::type Y; 
    typedef typename some_other_thing_using<X, Y>::type Z; 
    static const bool value = some_condition<X, Y, Z>::value; 
}; 

template <typename X> 
struct bar <std::vector<X>, 
      typename enable_if_c< 
       bar_enabled<X>::value 
      >::type> 
    { ... }; 

Pero por varias razones (entre ellas queriendo evitar un tipo separado, lo que complica lo que estoy haciendo), espero que exista una mejor solución. ¿Algunas ideas?

+1

por defecto no simulan nada. Proporcionan los valores predeterminados. –

+3

Para el registro, "La lista de parámetros de plantilla de una especialización no debe contener valores de argumento de plantilla predeterminados" '[C++ 11: 14.5.5/8]' –

+0

@LightnessRacesinOrbit, ¿quiere decir que este problema no? t cambiado en C++ 11, o algo más? – ajg

Respuesta

3

Tal vez usted puede pegarse a la distinción entre una clase base: argumentos

template <typename X, typename Y, bool> 
struct BaseImpl    { /* ... */ }; 

template <typename X, typename Y> 
struct BaseImpl<X, Y, true> { /* ... */ }; 

template <typename X, typename Y = typename weird_stuff<X>::type> 
struct Foo : BaseImpl<X, Y, some_condition<X, Y>::value> 
{ 
    // common stuff 
}; 
Cuestiones relacionadas