enum als string ausgeben?
-
Konrad Rudolph schrieb:
Think encapsulation. Mit einem
std::tr1::array<char, 3>sollte es doch wunderbar gehen, oder übersehe ich da etwas?Ist das
std::tr1::arraygleich demboost::array?
Dann gibt es nämlich Probleme, allerdings mehr in der Bequemlichkeit.
boost::arrayhat keine Konstruktoren, wodurch jegliche implizite Umwandlung unmöglich ist. Desweiteren haben mir noch keine rohen Strings, sondern alle sind noch mit einem '\0' abgeschlossen. Bsp:#include <boost/array.hpp> #include <map> #include <string> int main() { typedef boost::array<char, 3> Array_t; typedef std::map<Array_t, int> FirstMap_t; typedef std::map<std::string, int> SecondMap_t; Array_t tempArray; FirstMap_t firstMap; SecondMap_t secondMap; // Zuerst mit dem Array: char const* p = "abc"; tempArray.assign(p, p + 3); // Unter VS noch warnings ... firstMap[tempArray] = 0; // zusätzliche Kopie! // usw. // Dann mit dem std::string: secondMap["abc"] = 0; // irgendwie angenehmer, nicht? return 0; }Zudem wenn man noch bedenkt, was für Optimierungen der Compiler machen kann, dann würde ich persönlich bei einer
std::mapeher denstd::stringnehmen. Alles andere ist Mikrooptimierung, welche allenfalls später durchgeführt werden kann. Kann mir aber schlecht vorstellen, dass es dadurch einen Geschwindigkeitsverlust geben wird.Grüssli
-
Dravere schrieb:
Konrad Rudolph schrieb:
Think encapsulation. Mit einem
std::tr1::array<char, 3>sollte es doch wunderbar gehen, oder übersehe ich da etwas?Ist das
std::tr1::arraygleich demboost::array?
Dann gibt es nämlich Probleme, allerdings mehr in der Bequemlichkeit.
boost::arrayhat keine KonstruktorenDafür aber Array-Initializer, die hier evtl. sowieso besser geeignet sind.
typedef array<char, 3> tlc_t; typedef map<tlc_t, char, tlc_comp> tlc_to_aa_t; tlc_t a = {{ 'a', 'l', 'a' }}; tlc_t g = {{ 'g', 'l', 'y' }}; // … etc. tlc_to_aa_t tr; tr[a] = 'a'; tr[g] = 'g'; // … etc.Zudem wenn man noch bedenkt, was für Optimierungen der Compiler machen kann, dann würde ich persönlich bei einer
std::mapeher denstd::stringnehmen. Alles andere ist Mikrooptimierung, welche allenfalls später durchgeführt werden kann. Kann mir aber schlecht vorstellen, dass es dadurch einen Geschwindigkeitsverlust geben wird.Ha. Na ja. In unserem Bioinformatik-Software-Framework haben wir für alle möglichen Konvertierungen hartcodierte Übersetzungstabellen und die bringen definitiv einen Geschwindigkeitsvorteil. Aber zugegeben, hier sind solche Dinge auch wirklich wichtig.
-
Der Beitrag ist nicht ganz frisch, trotzdem wollte ich meinen Vorschlag auch posten. Ich habe für enum-string Konvertierung ein Perl-Skript geschrieben, das eine Klasse mit vielen überladenen toString-Methoden erzeugt.
Die C++ Dateien werden nicht mit Perl geparst sondern es wird zuvor die tags-Datei mit dem Tool ctags erzeugt.
Hier ist das Skript:#!/bin/perl # Valentin Heinitz, 2010-03-20 # Script for making C++ class which converts enum to string. # Version: 0.01 # This script is Public Domain. Copy, modify and redistribute it as you want. # The software is provided "as is", without warranty of any kind. # # Call it from Source-code root-directory with command-line: # perl enum2string.pl > <ToStringClassFileName.h> use strict; use warnings; #Found enum types will be added to this list my @etypes=(); #Found includes will be added to this list my @includes=(); # Pattern for searching enum types and corresponding include-file. my $pat="^[^\t]+\t([^\t]+)\t.*enum:([a-zA-Z_][a-zA-Z0-9_]*)"; my $file = "tags"; system "ctags -R *"; open T, ">tmp" or die "couldn't open tmp\n"; open F, $file or die "couldn't open $file\n"; #Replacing MS-Windows paths by UNIX paths (for includes) while (<F>) { $_ =~ s/\\/\//; print T "$_"; } close F; close T; $file="tmp"; open F, $file or die "couldn't open $file\n"; while (<F>) { if (my ($m) = m/$pat/){ $etypes[++$#etypes] = $2; $includes[++$#includes] = $1; #print "$_\n"; } } close F; #Class name to be generated. Change as you like, or set from argument my $clName = 'EnumToString'; #Remove duplicates from enum type list my %hlp1 = (); my @uniqenums = grep { ! $hlp1{$_} ++ } @etypes; #Remove duplicates from include list my %hlp2 = (); my @uniqinc = grep { ! $hlp2{$_} ++ } @includes; print "#ifndef _H_G__$clName\n"; print "#define _H_G__$clName\n\n"; print "#include <iostream>\nusing std::cout;\n"; foreach my $inc (@uniqinc) { print "#include \"$inc\"\n"; } print "\n\n"; print "class $clName {\n"; print " EnumToString(); // utility class, no instances\n\n"; print "public:\n"; foreach my $k (@uniqenums) { $pat = "^([a-zA-Z0-9_]*)\t.*e\tenum:$k"; print " static const char * toString( $k en ) {\n"; print " switch( en ) {\n"; open F, $file or die "couldn't open $file\n"; while (<F>) { if (my ($m) = m/$pat/){ print " case $1: return \"$1\";\n"; } } close F; print " }\n"; print " }\n\n"; } #Test print "static void testEnum2String() {\n"; foreach my $k (@uniqenums) { $pat = "^([a-zA-Z0-9_]*)\t.*e\tenum:$k"; print " std::cout << \"Enums of $k:\\n\";\n"; open F, $file or die "couldn't open $file\n"; while (<F>) { if (my ($m) = m/$pat/){ print " std::cout <<\" \"<< toString( $1 ) <<\" -> \" << $1 <<\"\\n\";\n"; } } close F; } print " }\n\n"; print "};\n\n"; print "#endif\n";Die komplete Beschreibung mit dem Beispielprojekt ist auf meiner Webseite zu finden:
http://heinitz-it.de/archives/date/2010/03Gruß,
Valentin Heinitz