Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>This is definitively possible (see below), but I'm not sure it's worth the trouble... Couldn't you use a simpler approach, perhaps with inheritance and polymorphism?</p> <p>Nevertheless, here is a working solution using Boost.MPL:</p> <pre><code>// MapperRow holds the necessary parsing informations: type of the member, // type of the object, pointer to the appropriate member, parsing function template&lt;typename Type, typename Clazz, Type Clazz::*Member, void (*Parser)(const std::string &amp;, Type &amp;)&gt; struct MapperRow { typedef Type type; typedef Clazz clazz; typedef Type Clazz::*memberType; static const memberType member; typedef void (*parserType)(const std::string &amp;, Type &amp;); static const parserType parser; }; template &lt;typename Type, typename Clazz, Type Clazz::*Member, void (*Parser)(const std::string &amp;, Type &amp;)&gt; const typename MapperRow&lt;Type, Clazz, Member, Parser&gt;::memberType MapperRow&lt;Type, Clazz, Member, Parser&gt;::member = Member; template &lt;typename Type, typename Clazz, Type Clazz::*Member, void (*Parser)(const std::string &amp;, Type &amp;)&gt; const typename MapperRow&lt;Type, Clazz, Member, Parser&gt;::parserType MapperRow&lt;Type, Clazz, Member, Parser&gt;::parser = Parser; // fill iterates over a map key-&gt;MapperRow, trying to find the given key. // if found, it calls the parsing function, otherwise it asserts false (should // probably throw an exception instead) template &lt;typename Clazz, typename First, typename Last&gt; struct fill_impl { static void apply(Clazz &amp;obj, const std::string &amp;key, const std::string &amp;value) { typedef typename mpl::deref&lt;First&gt;::type entry; static const char *curKey = mpl::c_str&lt; typename mpl::first&lt;entry&gt;::type &gt;::value; if (key == curKey) { typedef typename mpl::second&lt;entry&gt;::type Row; Row::parser(value, obj.*Row::member); } else { fill_impl&lt; Clazz, typename mpl::next&lt;First&gt;::type, Last &gt;::apply(obj, key, value); } } }; template &lt;typename Clazz, typename Last&gt; struct fill_impl&lt;Clazz, Last, Last&gt; { static void apply(Clazz &amp;obj, const std::string &amp;key, const std::string &amp;value) { assert(false &amp;&amp; "key not found"); } }; template &lt;typename Map, typename Clazz&gt; void fill(Clazz &amp;obj, const std::string &amp;key, const std::string &amp;value) { fill_impl&lt; Clazz, typename mpl::begin&lt;Map&gt;::type, typename mpl::end&lt;Map&gt;::type &gt;::apply(obj, key, value); } </code></pre> <p>Sample use:</p> <pre><code>template &lt;typename T&gt; void get_value_units(const std::string &amp;str, T &amp;value) { value = T::from_value(boost::lexical_cast&lt;typename T::value_type&gt;(str)); } template &lt;typename T&gt; void get_value_simple(const std::string &amp;str, T &amp;value) { value = boost::lexical_cast&lt;T&gt;(str); } typedef boost::units::quantity&lt;boost::units::si::energy&gt; Energy; typedef boost::units::quantity&lt;boost::units::si::length&gt; Length; struct DeathStar { Length radius; Energy energy; bool operational; int tie_fighters; }; // Could be clearer with MPLLIBS_STRING* typedef mpl::map&lt; mpl::pair&lt; mpl::string&lt;'deat','h_st','ar_r','adiu','s'&gt;, MapperRow&lt; Length , DeathStar, &amp;DeathStar::radius, &amp;get_value_units&lt;Length&gt; &gt; &gt;, mpl::pair&lt; mpl::string&lt;'deat','h_st','ar_e','nerg','y'&gt;, MapperRow&lt; Energy, DeathStar, &amp;DeathStar::energy, &amp;get_value_units&lt;Energy&gt; &gt; &gt;, mpl::pair&lt; mpl::string&lt;'oper','atio','nal'&gt;, MapperRow&lt; bool, DeathStar, &amp;DeathStar::operational, &amp;get_value_simple&lt;bool&gt; &gt; &gt;, mpl::pair&lt; mpl::string&lt;'num_','tie_','figh','ters'&gt;, MapperRow&lt; int, DeathStar, &amp;DeathStar::tie_fighters, &amp;get_value_simple&lt;int&gt; &gt; &gt; &gt; death_star_map; int main() { DeathStar ds; fill&lt;death_star_map&gt;(ds, "death_star_radius", "12"); fill&lt;death_star_map&gt;(ds, "death_star_energy", "34"); fill&lt;death_star_map&gt;(ds, "operational", "1"); fill&lt;death_star_map&gt;(ds, "num_tie_fighters", "56"); std::cout &lt;&lt; "Radius: " &lt;&lt; ds.radius &lt;&lt; '\n'; std::cout &lt;&lt; "Energy: " &lt;&lt; ds.energy &lt;&lt; '\n'; std::cout &lt;&lt; "Operational: " &lt;&lt; std::boolalpha &lt;&lt; ds.operational &lt;&lt; '\n'; std::cout &lt;&lt; "Tie fighters: " &lt;&lt; ds.tie_fighters &lt;&lt; '\n'; } </code></pre> <p>* <a href="http://abel.web.elte.hu/mpllibs/metaparse/MPLLIBS_STRING.html" rel="nofollow">MPLLIBS_STRING</a></p>
 

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