Reasonable key types for map used to set properties of related classes?
<p>I'm planning to write a code with classes that have inheritance relationships like the following and have various properties that are associated with material types:</p>

<ol>
<li>Abstract base class <code>Foo</code>. No properties associated with it.</li>
<li><code>Foo1GeneralElastic</code> inherits from class Foo and has the properties associated with a <em>possibly</em> anisotropic elastic material.</li>
<li><code>Foo2GeneralElastic</code> also inherits from class Foo and has the same kinds of material properties as <code>Foo1GeneralElastic</code>, but is otherwise different.</li>
<li><code>Foo1PiezoElastic</code> inherits from <code>Foo1GeneralElastic</code> and has both piezoelectric properties as well as generic elastic ones.</li>
<li><code>Foo1IsotropicElastic</code> inherits from <code>Foo1GeneralElastic</code>, but does not share its properties.</li>
</ol>

<p>I decided that the abstract base class would have one or more methods that take a map of type <code>MyPropMap</code>, defined as:</p>

<pre><code>typedef std::map&lt;PropertyLabel,std::vector&lt;double&gt; &gt; MyPropMap
</code></pre>

<p>I have a few different options on what the PropertyLabel type could be, and I'm trying to weigh the pros and cons of each:</p>

<p><strong>Have the PropertyLabel be an <code>enum</code></strong>: This would be lightweight, but it would basically be a bag of labels for all the different properties of every material that I'm considering.</p>

<p><strong>Have the PropertyLabel be just an <code>int</code></strong>: Here, I'd have separate header files for each material type, each of which would contain definition of static integer constants that would be labels for the relevant material properties. For example, <code>MatPropKeyGenElastic.hpp</code> would define the integer constant <code>ELASTICITY_MATRIX</code>, <code>MatPropKeyIsotropicElastic.hpp</code> would define the constants <code>ELASTIC_MODULUS</code> and <code>POISSONS_RATIO</code>, and <code>MatPropKeyPiezoElastic.hpp</code> would <code>#include</code> the file <code>MatPropKeyGenElastic.hpp</code> and additionally define the constant <code>PIEZO_CONST_MATRIX</code>.</p>

<p>The tricky thing would be to make sure that none of the constants that could be used together would have the same values. That could be accomplished by generating the header files with a script that would set the values of these constants to unique values.</p>

<p><strong>Have the PropertyLabel be a <code>std::string</code></strong> From here I could take things a few different ways. I could just have string literals like <code>"ELASTICITY_MATRIX"</code> in the code and rely on these literals never being misspelled---an error that would be caught at run-time rather than compile time. I could define string constants in way analogous to the scheme above for integer constants, and the task of keeping the constants unique would be trivial: just set the value of <code>ELASTICITY_MATRIX</code> to <code>"ELASTICITY_MATRIX"</code>, the value of <code>POISSONS_RATIO</code> to <code>"POISSONS_RATIO"</code>, etc.</p>

<p>The catch I see with that, aside from the extra overhead, is that I've seen horror stories relating to global static constants of non-PODs, such as those in the comments in the topics <a href="http://stackoverflow.com/questions/2151831/non-integral-constants/">non-integral constants</a> and <a href="http://stackoverflow.com/questions/459942/defining-class-string-constants-in-c/">Defining class string constants in C++?</a>. I suppose that I could have the global static constants be <code>const char[]</code> arrays, which are PODs that would be implicitly converted into <code>std::string</code>s when used as map keys (and, <em>no</em>, I am not planning on letting the map key itself be <code>const char*</code>). I could also define the string literals with the preprocessor, but then I couldn't keep them within a namespace.</p>

<p>Would you recommend any of the above approaches? Are there hidden traps in them that I hadn't noticed? Are there still other approaches that you would recommend?</p>
