Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I have created a simple templated class <code>streamable_enum</code> that uses stream operators <code>&lt;&lt;</code> and <code>&gt;&gt;</code> and is based on the <code>std::map&lt;Enum, std::string&gt;</code>: </p> <pre><code>#ifndef STREAMABLE_ENUM_HPP #define STREAMABLE_ENUM_HPP #include &lt;iostream&gt; #include &lt;string&gt; #include &lt;map&gt; template &lt;typename E&gt; class streamable_enum { public: typedef typename std::map&lt;E, std::string&gt; tostr_map_t; typedef typename std::map&lt;std::string, E&gt; fromstr_map_t; streamable_enum() {} streamable_enum(E val) : Val_(val) {} operator E() { return Val_; } bool operator==(const streamable_enum&lt;E&gt;&amp; e) { return this-&gt;Val_ == e.Val_; } bool operator==(const E&amp; e) { return this-&gt;Val_ == e; } static const tostr_map_t&amp; to_string_map() { static tostr_map_t to_str_(get_enum_strings&lt;E&gt;()); return to_str_; } static const fromstr_map_t&amp; from_string_map() { static fromstr_map_t from_str_(reverse_map(to_string_map())); return from_str_; } private: E Val_; static fromstr_map_t reverse_map(const tostr_map_t&amp; eToS) { fromstr_map_t sToE; for (auto pr : eToS) { sToE.emplace(pr.second, pr.first); } return sToE; } }; template &lt;typename E&gt; streamable_enum&lt;E&gt; stream_enum(E e) { return streamable_enum&lt;E&gt;(e); } template &lt;typename E&gt; typename streamable_enum&lt;E&gt;::tostr_map_t get_enum_strings() { // \todo throw an appropriate exception or display compile error/warning return {}; } template &lt;typename E&gt; std::ostream&amp; operator&lt;&lt;(std::ostream&amp; os, streamable_enum&lt;E&gt; e) { auto&amp; mp = streamable_enum&lt;E&gt;::to_string_map(); auto res = mp.find(e); if (res != mp.end()) { os &lt;&lt; res-&gt;second; } else { os.setstate(std::ios_base::failbit); } return os; } template &lt;typename E&gt; std::istream&amp; operator&gt;&gt;(std::istream&amp; is, streamable_enum&lt;E&gt;&amp; e) { std::string str; is &gt;&gt; str; if (str.empty()) { is.setstate(std::ios_base::failbit); } auto&amp; mp = streamable_enum&lt;E&gt;::from_string_map(); auto res = mp.find(str); if (res != mp.end()) { e = res-&gt;second; } else { is.setstate(std::ios_base::failbit); } return is; } #endif </code></pre> <p>Usage:</p> <pre><code>#include "streamable_enum.hpp" using std::cout; using std::cin; using std::endl; enum Animal { CAT, DOG, TIGER, RABBIT }; template &lt;&gt; streamable_enum&lt;Animal&gt;::tostr_map_t get_enum_strings&lt;Animal&gt;() { return { { CAT, "Cat"}, { DOG, "Dog" }, { TIGER, "Tiger" }, { RABBIT, "Rabbit" } }; } int main(int argc, char* argv []) { cout &lt;&lt; "What animal do you want to buy? Our offering:" &lt;&lt; endl; for (auto pr : streamable_enum&lt;Animal&gt;::to_string_map()) { // Use from_string_map() and pr.first instead cout &lt;&lt; " " &lt;&lt; pr.second &lt;&lt; endl; // to have them sorted in alphabetical order } streamable_enum&lt;Animal&gt; anim; cin &gt;&gt; anim; if (!cin) { cout &lt;&lt; "We don't have such animal here." &lt;&lt; endl; } else if (anim == Animal::TIGER) { cout &lt;&lt; stream_enum(Animal::TIGER) &lt;&lt; " was a joke..." &lt;&lt; endl; } else { cout &lt;&lt; "Here you are!" &lt;&lt; endl; } return 0; } </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload