2010-08-01 7 views
2

J'écris un module avec des modèles mixins pour fournir une fonction main aux fins de tests unitaires. L'utilisation est comme suit:signatures de fonction de test avec ParameterTypeTuple

/* For modules without their own main, e.g. libraries. 
* main is conditionally supplied using version(unittest). 
*/ 
mixin Main; 

/* For executable modules defining function "realMain". 
* Generated main has the same signature and return type 
* as realMain, and transfers control to it. Additionally, 
* main exits without calling realMain for version (unittest). 
*/ 
mixin Main!realMain; 

L'idée est que tous les modules de mes mélange dans main appropriée, de sorte que:

  • Les bibliothèques ne ont pas besoin --main passé à rdmd, parce
  • Il ne semble pas bon moyen de décider pas de passer --main pour les modules qui définissent leur propre, lors de l'exécution automatique des tests unitaires pour chaque fichier dans un di hiérarchie rectorat - le code de sortie de rdmd est le même que pour une compilation a échoué.

J'utilise std.traits pour déterminer la validité de realMain en fonction main, et faire en sorte que mon généré main a la même signature. Tout semble fonctionner, mais je pense que ça pourrait être plus propre. À l'heure actuelle, mon modèle pour vérifier main valides arguments ressemble à ceci:

template isMainArgTypes(alias main) 
{ 
    static if (is(ParameterTypeTuple!main == TypeTuple!())) 
     enum isMainArgTypes = true; 
    else static if (ParameterTypeTuple!main.length == 1 
     && is(ParameterTypeTuple!main[0] T : const T[])) 
    { 
     enum isMainArgTypes = is(T : const char[]); 
    } 
    else 
     enum isMainArgTypes = false; 
} 

Je suis sûr qu'il doit y avoir un moyen de condenser la condition moyenne en une seule expression is, sans tester explicitement la longueur de tuple et de vérifier séparément pour un type de chaîne, mais jusqu'à présent, ma métaprogramming-fu naissante a échoué.

Toutes les idées, les magiciens D?

Répondre

1

Vous pouvez essayer la comparer à un type de fonction:

enum isMainArgTypes = is(typeof(&main) == int function()) || 
         is(typeof(&main) == void function()) || 
         is(typeof(&main) == int function(string[])) || 
         is(typeof(&main) == void function(string[])); 

Pas plus court, mais il semble plus propre car il n'a pas besoin static if

+0

Merci pour la réponse. L'avantage de ne pas tester spécifiquement les fonctions est que vous pouvez utiliser d'autres types de valeurs appelables, mais je suis d'accord, c'est plus propre. Il semble également que le plus proche nous avons des exemples de D idiomatique à l'heure actuelle proviennent de la source Phobos :) – shambulator