String auf Enum Mappen



  • Mit dem Tool GNU gperf kann man sich C oder C++ Code erzeugen lassen, der dieses Mapping mittels einer Perfect Hash Function erledigt. Dürfte auch performant sein.

    http://www.gnu.org/software/gperf/

    Tutorial: http://www.ibm.com/developerworks/linux/library/l-gperf/index.html



  • cooky451 schrieb:

    Ich habe MinGW, mit Version 4.7. .. ist das schon wieder zu alt?^^

    ne die 4.7er reihe ist die aktuelle.
    Hast du bei deinen Tests das programm nur einmal laufen lassen oder mehrmals?



  • Mehrmals, mache ich immer so, hat sich nichts geändert. Schon komisch.


  • Mod

    Hier ein paar Ergebnisse mit einem Atom

    Linux 3.7.0-hardened x86_64 Intel(R) Atom(TM) CPU 330 @ 1.60GHz  übertaktet auf 2 Ghz
    g++ (Gentoo Hardened 4.5.4 p1.0, pie-0.4.7) 4.5.4 für x86_64 und x86 ABI
    g++ (Gentoo 4.7.2 p1.3, pie-0.5.5) 4.7.2 für x32 ABI
    Kompiliert mit
    g++ -std=c++0x -O3 -march=native test.cpp
    zusätzlich -fomit-frame-pointer im x86-Fall
    jeweils 10M Iterationen
    						x86_64		x86			x32
    to_animal_naive:		2.3351		2.22243		2.39634
    to_animal_naive_map:	5.98775		5.8825		4.47632
    to_animal_map:			3.59247		1.77951		2.08863
    to_animal_unordered_map:5.26436		5.13893		4.00907
    to_animal_switch_only:	1.09334		0.747978	0.672978
    to_animal_if_only:		1.06588		0.695158	0.667932
    to_animal_nice_mix:		1.08924		0.758383	0.726613
    


  • Ich muss gestehen, an einer TMP Lösung hätte ich durchaus Interesse. Leider weiß ich nicht wirklich wie das funktionieren sollte.. niemand eine Idee? Nach dem TMP Brainfuck Interpreter sollte das doch möglich sein. 😃



  • cooky451 schrieb:

    Ich muss gestehen, an einer TMP Lösung hätte ich durchaus Interesse. Leider weiß ich nicht wirklich wie das funktionieren sollte.. niemand eine Idee? Nach dem TMP Brainfuck Interpreter sollte das doch möglich sein. 😃

    Leider hat C++ keine Compile-Time-Reflection. In D würde das gehen.



  • Natuerlich geht sowas. Nur leider nicht automatisch. Man muesste eben String-Werte selbst angeben.



  • Ich hatte ein bisschen Langeweile, also habe ich sowas gleich mal implementiert.

    Verwendungsbeispiel:

    #include <iostream>
    
    enum struct my_enum : unsigned
    {
    	foo,
    	bar,
    	baz,
    	qux,
    };
    
    // Zum ueberpruefen
    std::ostream& operator << (std::ostream& os, my_enum e)
    {
    	static char const* const table[] = { "foo", "bar", "baz", "qux" };
    	return os << table[static_cast<unsigned>(e)];
    }
    
    int main()
    {
    	typedef tmp::enum_mapper
    	<
    		my_enum,
    		// Reihenfolge der Eintraege egal, wird intern sowieso sortiert
    		EMAP(my_enum::baz, 'b','a','z'),
    		EMAP(my_enum::bar, 'b','a','r'),
    		EMAP(my_enum::foo, 'f','o','o'),
    		EMAP(my_enum::qux, 'q','u','x')
    	> my_enum_mapper;
    
    	my_enum_mapper mapper;
    
    	std::cout << mapper("foo") << '\n';
    	std::cout << mapper("bar") << '\n';
    	std::cout << mapper("baz") << '\n';
    	std::cout << mapper("qux") << '\n';
    
    	try
    	{
    		std::cout << mapper("garbage") << '\n';
    	}
    
    	catch(std::invalid_argument const& iv)
    	{
    		std::cout << iv.what() << '\n';
    	}
    }
    

    foo
    bar
    baz
    qux
    string 'garbage' has no enum value

    https://ideone.com/3cwMzU

    Auf Zeit messen habe ich allerdings jetzt keine Lust mehr, das darf jemand anderes machen. :xmas1:



  • Der ganze Aufwand...und dann wird doch insgesamt 10 mal strcmp aufgerufen.



  • Dann mach mal einen Vorschlag, wie man es besser machen koennte...



  • Der nächste Schritt wäre, einen Compile-Time-Trie aufzubauen.



  • Genau das mache ich doch durch die Rekursion?!



  • Ich habe mal dem enum ball hinzugefügt und ein paar Debugausgaben gemacht:

    cmp ball with baz
    cmp ball with bar
    cmp ball with ball

    Hier ist es eigentlich nicht nötig, die ersten zwei Zeichen zu vergleichen. Besser:

    cmp ll with z
    cmp ll with r
    cmp ll with ll

    Das meinte ich mit Trie (!= Tree).

    Btw: Dein "struct constant" ist das gleiche wie std::integral_constant.



  • @cooky451: Definiere doch mal static animal_selector selector ausserhalb der Funktion als echte globale Variable und messer erneut. Bei der aktuellen Variante sollte ein Guard bzw. eine if-Abfrage generiert werden, die bei diesem Spielzeugbeispiel eine Menge Zeit kosten koennte.


Anmelden zum Antworten