2009-07-10 15 views
5
template<typename T> 
class vec3 
{ 
public: 
    typename T type_t; 
    T x; 
    T y; 
    T z; 
}; 

template<typename T> 
struct numeric_type_traits_basic_c 
{ 
    typedef T type_t; 
    typedef T scalar_t; 
}; 

template<typename T> 
struct numeric_type_traits_vec3_c 
{ 
    typedef T type_t; 
    typedef typename T::type_t scalar_t; 
}; 

typedef numeric_type_traits_basic_c<int> int_type_traits; 
typedef numeric_type_traits_vec3_c< vec3<int> > vec3_int_type_traits; 

caracteres de tipo escalar y vector, la única diferencia es que el tipo escalar, para un vector, es el tipo de su elemento. Funciona bien.rasgos de tipo especialización

Pero me gustaría poder usar el mismo nombre para esas dos clases.

template<typename T> 
struct numeric_type_traits_c 
{ 
    typedef T type_t; 
    typedef ????? scalar_t; 
}; 

Sé que esto es posible hacerlo si la clase es explícitamente especializado para cada tipo que necesito: int, float, vec3, vec3 ...

Eso es un montón de duplicación ... ¿Cómo ¿Puedo mantener la simplicidad del primer bit de código pero tener el mismo nombre de clase al mismo tiempo?

Respuesta

5

Esta es la sintaxis para la especialización de plantilla de clase parcial:

template<typename T> 
struct numeric_type_traits // basic template 
{ 
    typedef T type_t; 
    typedef T scalar_t; 
}; 

template<typename T> 
struct numeric_type_traits< vec3<T> > // partial specialisation for vec3's 
{ 
    typedef vec3<T> type_t; 
    typedef T scalar_t; 
}; 

Y así sucesivamente, por ejemplo:

template <typename T, typename T_Alloc> 
struct numeric_type_traits< std::vector<T,T_Alloc> > // part. spec. for std::vector 
{ 
    typedef std::vector<T,T_Alloc> type_t; // deal with custom allocators, too 
    typedef T scalar_t; 
}; 
0

¿Tal vez debería crear una instancia de su plantilla con dos tipos? Ver:

template<typename TYPE, typename SCALAR> 
struct numeric_type_traits_c 
{ 
    typedef TYPE type_t; 
    typedef SCALAR scalar_t; 
}; 

typedef numeric_type_traits_c<int,int> int_type_traits; 
typedef numeric_type_traits_c<vec3<int>, vec3<int>::type_t> vec3_type_traits; 
+0

La intención detrás del rasgo de tipo es evitar eso ya que el rasgo de tipo se supone que debe proporcionarle dicha información –

0
template<typename T> 
struct numeric_type_traits_c 
{ 
     typedef T type_t; 
     typedef T scalar_t; 
}; 

template<typename T> 
struct numeric_type_traits_c<vec3<T> > 
{ 
     typedef vec3<T> type_t; 
     typedef typename vec3<T>::type_t scalar_t; 
}; 

Sí, seguro que he cometido un error en type_t para vec3!

0

Una observación interesante aquí radica en aplicar el conocimiento que se tiene del polimorfismo dinámico para el polimorfismo 'función de tipo'.

Si se compara esta función f:

struct I { virtual double f()const = 0; }; // C++ version of 'an interface' 
struct A : public I { virtual double f()const{ return 0; } }; 
struct B : public I { virtual double f()const{ return 1; } }; 
struct C { }; 

void f(const I& i){ return I.f(); } 

f(A()); 
f(C()); // compiler warning: wrong type provided. 

con esta función f:

// struct TI { typedef ??? iT; }; // no C++ version of a type-interface 
struct TA { typedef int iT; }; 
struct TB { typedef double iT; }; 
struct TC { }; 

template< typename aTI > struct fT { typedef aTI::iT returnType; }; 

fT<TA>::returnType vA; 
ft<C>::returnType vC; // compiler error: C has no iT member. 

Usted ve que la única diferencia es la notación de los parámetros. La primera función es una función polimórfica "regular". El compilador nos advertirá si el argumento proporcionado no es del tipo correcto.

fT es una función que solo puede ser utilizada por el compilador para determinar un tipo determinado. Toma un tipo como argumento. Pero el lenguaje no tiene un "concepto" de restricción de tipo (aún - vea Conceptos en C++ 0x). Por lo tanto, debemos garantizar manualmente que los tipos que utilizamos para una función de tipo 'implementen' la interfaz correcta.

En concreto, esto se reduce a agregar el tipo scalar_t a cualquier clase que desee utilizar con la función de tipo numeric_type_traits_c.