2012-06-15 26 views
6

En una plantilla, quiero profundizar en el parámetro de plantilla al tipo real sin plantilla. Por lo tanto:Rasgos de tipo C++ para extraer la clase de parámetro de plantilla

template <typename T> 
struct MyTemplate 
{ 
    // sadly there's no extract_Base 
    typedef typename extract_base<T>::MyType WorkType; 
}; 
struct X {}; 
template <typename T> struct Templ {}; 
//MyTemplate<Templ<X>>::WorkType is X; 
//MyTemplate<X>::WorkType is X; 

La única solución que veo es verdadera para definir el tipo base como std :: vector <X> :: value_type es X. Pero tengo curiosidad si hay una manera de hacer esto sin definir los tipos de auxiliares en el interior cada plantilla de destino

Vi algo así como http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2965.html pero esto es borrador? y no lo entiendo del todo

Sí, sé que hay herencia múltiple, pero incluso para casos simples, sería bueno.

ACTUALIZACIÓN: la solución de Nawaz me funciona muy bien, y es fácil de extender a casos específicos, p.

template<template<typename, typename> class X, typename T1, typename T2> 
struct extract_base <X<T1, T2>> //specialization 
{ 
    typedef T1 base; 
}; 

Incluso puedo aplicar is_base_of u otros filtros a T1/T2 y así sucesivamente. Entonces funciona para X < T, U > - al menos con g ++ 4.6.7.

+0

Esto no tiene nada que ver con la herencia o las clases base. –

+0

Hay 'std :: is_base_of', pero eso puede no satisfacer sus propósitos por completo. – dirkgently

Respuesta

7

En primer lugar, vamos a llamarlo value_type en lugar de base, porque value_type parece ser el término más apropiado para describir el tipo que desea extraer.

Puede utilizar este:

template<typename T> 
struct extract_value_type //lets call it extract_value_type 
{ 
    typedef T value_type; 
}; 

template<template<typename> class X, typename T> 
struct extract_value_type<X<T>> //specialization 
{ 
    typedef T value_type; 
}; 

debería funcionar siempre y cuando el argumento de plantilla para extract_value_type es de la forma de cualquiera de T o X<T>. Sin embargo, no funcionará para X<T,U>. Pero luego es fácil implementarlo en C++ 11 usando una plantilla variadica.

Se usa como:

template <typename T> 
struct MyTemplate 
{ 
    typedef typename extract_value_type<T>::value_type value_type; 
}; 

demostración en línea: http://ideone.com/mbyvj


Ahora en C++ 11, puede utilizar la plantilla para hacer variadic extract_value_type trabajo con plantillas de clase que tienen más de una argumentos de plantilla, tales como std::vector, std::set, std::list etc.

template<template<typename, typename ...> class X, typename T, typename ...Args> 
struct extract_value_type<X<T, Args...>> //specialization 
{ 
    typedef T value_type; 
}; 

Demostración: http://ideone.com/SDEgq

+0

¡Compila con "plantilla clase X" y funciona! Gracias. – queen3

+0

@ queen3: Ahora vea la solución variadica. – Nawaz

+0

Sí, aunque X funcionó para mí, mira la actualización. Sin embargo eso era lo que necesitaba. – queen3

Cuestiones relacionadas