2011-02-03 11 views
16

Obviamente, no se puede tener una instancia de tipo void en un programa bien formado, así que algo como la siguiente declaración no se compilará:tipo void en std :: tupla

std::tuple<void, double, int> tup; 

Sin embargo, como Siempre que tratemos estrictamente tipos en lugar de objetos, no parece haber ningún problema. Por ejemplo, mi compilador (GCC) me permite decir:

typedef std::tuple<void, double, int> tuple_type; 

Esto es interesante para mí, porque parece que con C++ 0x podemos simplemente utilizar std::tuple para llevar a cabo una gran cantidad de los trucos de programación que los meta antes habría requerido la biblioteca boost::mpl. Por ejemplo, podemos usar std::tuple para crear un vector de tipos.

Por ejemplo, supongamos que queremos crear un vector de tipos que representan una función de firma:

Sólo podemos decir:

template <class R, class... Args> 
struct get_function_signature; 

template <class R, class... Args> 
struct get_function_signature<R(*)(Args...)> 
{ 
    typedef std::tuple<R, Args...> type; 
}; 

Esto parece funcionar, incluso si la firma de la función tiene un void tipo, siempre que nunca instanciamos una instancia de get_function_signature<F>::type.

Sin embargo, C++ 0x todavía es nuevo para mí, y por supuesto todas las implementaciones son aún algo experimentales, así que estoy un poco incómodo con esto. ¿Podemos realmente usar std::tuple como un vector de tipos para meta-programación?

+1

Espero que el 'boost :: mpl :: vector' sea obsoleto. De todos modos, la mayoría de la funcionalidad 'boost :: mpl' y metaprogramación de plantillas en general cambiará considerablemente cuando aumente el soporte para plantillas variadic. –

Respuesta

10

Se hace realmente sentido de que se puede hacer

typedef std::tuple<void, double, int > tuple_type;

todo el tiempo que lo utiliza solamente como una lista de tipos para usar en tuple_element. Así que puedo hacer

tuple_element<0,tuple_type>::type * param;

que se declaran como parámetro void*

+0

Parece que algunas implementaciones de bibliotecas estándar no pueden manejar esto incluso después de años de otras implementaciones de bibliotecas estándar que lo soportan sin problemas. Por ejemplo, GCC y Clang lo rechazan a menos que Clang esté usando la biblioteca estándar de MSVC, y MSVC lo acepta. –

0

Probablemente, tuple con void elemento es segura a menos que instanciamos.
Por lo tanto, aunque no podemos escribir como la siguiente,

struct C : std::tuple<void> {... 

No me puedo imaginar el caso de que este uso es útil ahora. Entonces, no importará.

Bueno, esto también se aplica a std::pair. Podemos escribir la lista de tipo simple como la siguiente:

struct Nil; 
typedef std::pair< void, std::pair< int, Nil > > t; 

aunque de alguna manera tal uso pair parece ser rara.

Por cierto, la lista de tipos tuple puede fallar en algún propósito tipo SFINAE. Por ejemplo, el siguiente código no está compilado en ideone (gcc-4.5.1) cuando probado:

std::tuple<void> f(); 
template< class T > char g(T const&); 

int main() { 
    sizeof g(f()); 
} 

Por lo tanto, no estoy seguro de que las listas actuales de tipo pueden ser sustituidos totalmente con tuple en un futuro próximo.