2011-02-11 14 views
6

Cuando es práctico para pasar rasgos como los parámetros de plantilla en lugar de simplemente utilizar algunos rasgos existentes struct gustarasgos y características que pasan como parámetros de plantilla

typedef basic_ofstream< char, char_traits<char> >

vs

typedef basic_ofstream<char>?

tengo algunas clases de azulejo que me gustaría tener algunos puntos en común (rasgos), por lo que he diseñado tile_traits para contener toda la información básica sobre una baldosa, como int_type y flag_type, así:

//unspecialized 
template<typename T> struct tile_traits; 
//... other stuff here, declaration of a tile class 
template<> 
struct tile_traits<tile_class> 
{ 
    typedef tile_class::int_type int_type; 
    typedef tile_class::flag_type flag_type; 
    //other possible tile info here. 
} 

Está diseñando rasgos como tales considerados como rasgos-blob?

+0

Term traits-blob era desconocido para mí. Se menciona en otra pregunta http://stackoverflow.com/questions/1870627/type-traits-definition-traits-blobs-metafunctions – Suma

Respuesta

12

El diseño de los rasgos es tanto arte como cualquier otra cosa. No hay respuestas rápidas y aquí. Creo que esta pregunta no ha sido respondida porque es imposible dar una buena respuesta sin saber mucho más sobre el problema que está solucionando.

En general, las clases de rasgos son un útil "punto de personalización". Es decir, si está diseñando una plantilla:

template <class Tile> 
class TileContainer 
{ 
    ... 
}; 

TileContainer podría hacer uso de tile_traits<Tile> para algunas propiedades de la teja. Y el cliente de TileContainer puede especializarse tile_traits<MyTile> para comunicar variaciones de las propiedades cuando el rasgo predeterminado (si existe) no es correcto.

Hasta ahora, no creo haber dicho nada que usted no sepa (a juzgar por el , como está formulada su pregunta).

Creo que su pregunta es:

en caso de que el diseño:

A)

template <class Tile, class Traits = tile_traits<Tile>> 
class TileContainer 
{ 
    // uses Traits 
}; 

o:

B)

template <class Tile> 
class TileContainer 
{ 
    // uses tile_traits<Tile> 
}; 

Hay ejemplos de ambos d se indica en C++ 03 y los próximos estándares de C++ 0x.

diseños

Ejemplo A:

template<class charT, class traits = char_traits<charT>, 
         class Allocator = allocator<charT>> 
    class basic_string; // both traits and Allocator are traits 

template <class Codecvt, class Elem = wchar_t, 
         class Tr = char_traits<Elem>> 
    class wbuffer_convert; 

template <class T, class Allocator = allocator<T>> 
    class vector; // Allocator is a A-trait that uses another 
        // B-trait internally: allocator_traits<Allocator> 

template <class charT, class traits = regex_traits<charT>> 
    class basic_regex; 

diseños Ejemplo B:

template<class Iterator> struct iterator_traits; 
template <class Alloc> struct allocator_traits; 
template <class Ptr> struct pointer_traits; 
template <class Rep> struct treat_as_floating_point; 
template <class Rep> struct duration_values; 

Mi único consejo es que no hay derecho o mal diseño. Uso:

template <class Tile> 
class TileContainer 
{ 
    // uses tile_traits<Tile> 
}; 

cuando esté seguro de que las necesidades de sus clientes siempre se pueden cumplir mediante la especialización tile_traits<MyTile>.

Uso:

template <class Tile, class Traits = tile_traits<Tile>> 
class TileContainer 
{ 
    // uses Traits 
}; 

cuando se sospecha que su cliente puede necesitar diferentes rasgos de la misma Mosaico o cuando se quiere forzar el tipo de TileContainer a ser diferente cuando algún rasgo que no sea tile_traits es usado.

+0

Esto prácticamente resume todas mis dudas sobre la pregunta n. ° 1. Creo que la respuesta a la pregunta n. ° 2 es, como dijiste, casi imposible tener una buena respuesta y está más relacionada con el estilo, creo que puedo ir con lo que ** Metaprogramación de plantillas de C++ ** tiene que decir sobre por ahora –

6

Necesita tener la clase de rasgos como un parámetro de plantilla si puede ver que las personas pasarían diferentes rasgos para el mismo tipo de datos. Si tus fichas siempre tendrán los mismos tile_traits para cada T, puedes usar eso directamente.

Si puede ver que alguien, a veces, usará my_special_traits, debe tenerlo como un parámetro de plantilla separado.

1

Al ver que puede proporcionar valores predeterminados para los rasgos, y teniendo el parámetro de rasgos siempre es más flexible, elegiría este enfoque a menos que tenga algunas razones específicas por las que no puede hacerlo.

template<class Bar,class Traits=FooTraits<Bar> > 
class Foo 
{}; 
+0

Leyendo la pregunta una vez más, admito que la respuesta quizás no esté relacionada con ella, ya que en el segundo leyendo Realmente no sé de qué se trata esta pregunta. No parece estar relacionado con la definición de la clase de las plantillas Foo, solo con los rasgos en sí. Allí la respuesta es simple: cuando los rasgos ya hechos le convengan, utilícelos, cuando no, proporcione los suyos. – Suma

Cuestiones relacionadas