2011-02-03 2 views
16

De toute évidence, vous ne pouvez pas avoir une instance de type void dans un programme bien formé, donc quelque chose comme la déclaration suivante ne compilera pas:Type Void dans std :: tuple

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

Cependant, Tant que nous traitons strictement des types par opposition aux objets, il ne semble pas y avoir de problème. Par exemple, mon compilateur (GCC) me permet de dire:

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

Cela me est intéressant, parce qu'il semble que, avec C++ 0x nous pouvons simplement utiliser std::tuple pour effectuer beaucoup de tours de méta-programmation qui plus tôt aurait eu besoin de la bibliothèque boost::mpl. Par exemple, nous pouvons utiliser std::tuple pour créer un vecteur de types.

Par exemple, supposons que nous voulons créer un vecteur de types représentant une signature de fonction:

Nous pouvons simplement dire:

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; 
}; 

Cela semble fonctionner, même si la signature de la fonction a un void type, tant que nous n'instancions jamais réellement une instance de get_function_signature<F>::type.

Cependant, C++ 0x est encore nouveau pour moi, et bien sûr toutes les implémentations sont encore un peu expérimentales, donc je suis un peu inquiet à ce sujet. Peut-on vraiment utiliser std::tuple comme vecteur de types pour la méta-programmation?

+1

Je m'attends à ce que 'boost :: mpl :: vector' soit déprécié. Quoi qu'il en soit, la plus grande partie de la fonctionnalité boost :: mpl' et de la métaprogrammation de modèles en général changera considérablement lorsque le support des modèles variés augmentera. –

Répondre

10

Il ne fait réellement sens que vous pouvez faire

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

aussi longtemps que vous ne l'utilisez comme un type liste à utiliser sur tuple_element. Ainsi, je peux faire

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

qui déclare param void*

+0

Il semble que certaines implémentations de bibliothèque standard ne peuvent pas gérer cela même après des années d'autres implémentations de bibliothèques standard le supportant sans problème. Par exemple, GCC et Clang le rejettent à moins que Clang n'utilise la bibliothèque standard de MSVC, et MSVC l'accepte. –

0

Probablement, tuple avec l'élément void est sûr que si nous instancier.
Ainsi, bien que nous ne pouvons pas écrire comme suit,

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

Je ne peux pas imaginer le cas où cet usage est maintenant utile. Donc, cela n'aura pas d'importance.

Eh bien, cela s'applique également à std::pair. Nous pouvons écrire simplement la liste de type comme suit:

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

bien en quelque sorte une telle utilisation pair semble être rare. Par ailleurs, la liste de types tuple peut échouer dans un but similaire à celui de SFINAE. Par exemple, le code suivant n'est pas compilé sur ideone (gcc-4.5.1) quand je testé:

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

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

Donc, je ne suis pas sûr que les listes de type courant peuvent être remplacés complètement avec tuple dans un avenir proche.

Questions connexes