La solution naïve, bien sûr, est d'écrire une fonction pour chaque énumération qui effectue la conversion en chaîne de caractères:
enum OS_type { Linux, Apple, Windows };
inline const char* ToString(OS_type v)
{
switch (v)
{
case Linux: return "Linux";
case Apple: return "Apple";
case Windows: return "Windows";
default: return "[Unknown OS_type]";
}
}
Ceci, cependant, est un entretien de catastrophe. Avec l'aide de la poussée.Préprocesseur de la bibliothèque, qui peut être utilisé à la fois avec code C et C++, vous pouvez facilement profiter de la préprocesseur et laisser générer cette fonction pour vous. La génération de macro est comme suit:
#include <boost/preprocessor.hpp>
#define X_DEFINE_ENUM_WITH_STRING_CONVERSIONS_TOSTRING_CASE(r, data, elem) \
case elem : return BOOST_PP_STRINGIZE(elem);
#define DEFINE_ENUM_WITH_STRING_CONVERSIONS(name, enumerators) \
enum name { \
BOOST_PP_SEQ_ENUM(enumerators) \
}; \
\
inline const char* ToString(name v) \
{ \
switch (v) \
{ \
BOOST_PP_SEQ_FOR_EACH( \
X_DEFINE_ENUM_WITH_STRING_CONVERSIONS_TOSTRING_CASE, \
name, \
enumerators \
) \
default: return "[Unknown " BOOST_PP_STRINGIZE(name) "]"; \
} \
}
La première macro (en commençant par X_
) est utilisée en interne par le second. La deuxième macro génère d'abord l'énumération, puis génère un ToString
fonction qui prend un objet de ce type et retourne le nom de l'agent recenseur comme une chaîne de caractères (cette mise en œuvre, pour des raisons évidentes, exige que les agents recenseurs de la carte pour les valeurs uniques).
En C++, vous pourriez mettre en œuvre l' ToString
fonction operator<<
de surcharge à la place, mais je pense que c'est un peu plus propre pour exiger un explicite "ToString
" pour convertir la valeur en la forme d'une chaîne.
Comme exemple d'utilisation, votre OS_type
énumération serait définie comme suit:
DEFINE_ENUM_WITH_STRING_CONVERSIONS(OS_type, (Linux)(Apple)(Windows))
Alors que la macro apparaît à première vue comme c'est beaucoup de travail, et la définition de l' OS_type
semble assez étrangère, n'oubliez pas que vous avez à écrire la macro une fois, alors vous pouvez l'utiliser pour chaque énumération. Vous pouvez ajouter des fonctionnalités supplémentaires (par exemple, une chaîne formulaire enum conversion) sans trop de difficulté, et il résout complètement le problème de l'entretien, puisque vous n'avez qu'à fournir les noms une fois, lors de l'appel de la macro.
L'énumération peut ensuite être utilisé comme si c'était définie normalement:
#include <iostream>
int main()
{
OS_type t = Windows;
std::cout << ToString(t) << " " << ToString(Apple) << std::endl;
}
Les extraits de code dans ce post, en commençant par l' #include <boost/preprocessor.hpp>
de la ligne, peut être compilé comme affiché à démontrer la solution.
Cette solution est pour le C++ car il utilise C++, la syntaxe spécifique (par exemple, pas de typedef enum
) et de surcharge de fonctions, mais il serait très simple pour faire ce travail avec C ainsi.