Comparing two sets with different type of values
<p>Here is the requirement:  </p>

<p>I've got a list of properties. Each property has a tag of type int and a value of one of the following types: (bool, char, string, int, long).
some sample properties:</p>

<blockquote>
  <p>tag: 1, value: "some string"<br>
  tag: 14, value: true<br>
  tag: 20, value: 123</p>
</blockquote>

<p>There is also a list of rules. Each rule is like a property, plus one of the following operators: (&lt;, >, &lt;=, >=, ==, !=, startsWith). The <em>startsWith</em> operator is used to check whether one string starts with another one.</p>

<p>Some sample rules:</p>

<blockquote>
  <p>tag: 1, value: "hello",  operator: ==<br>
  tag: 14, value: true, operator: ==  </p>
</blockquote>

<p>Each list of rules is called a <code>Criteria</code> and is used to validate a list of properties. A criteria validates a list of properties if only all the rules of the criteria are met. For example, the two rules above make up a criteria. This criteria does not validate the aforementioned list of properties because the 1st rule forces the value of tag (1) to be equal (==) to "hello" which is not. </p>

<p>The following criteria:</p>

<blockquote>
  <p>tag: 1, value: "some string",  operator: ==<br>
  tag: 20, value: 100, operator: ><br>
  tag: 20, value: 120, operator: &lt;</p>
</blockquote>

<p>does not validate the above properties too, because although the first two rules are met, the last rule, which forces the value of tag (20) to be less than 120 is not true. Therefore the whole criteria does not validate the properties.<br>
And here is a criteria that validates to true:</p>

<blockquote>
  <p>tag: 1, value: "some",  operator: startsWith<br>
  tag: 14, value: false, operator: !=<br>
  tag: 20, value: 123, operator: >=<br>
  tag: 20, value: 100, operator: ></p>
</blockquote>

<p>So far I have come up with the following code. But I am stuck in the implementation of <code>StartsWith</code> operator. Maybe I should of chosen a totally different approach to solve this problem. Any advice and help would be greatly appreciated! </p>

<pre><code>#include &lt;string&gt;
#include &lt;iostream&gt;
#include &lt;set&gt;
#include &lt;algorithm&gt;
#include &lt;tr1/memory&gt;

using namespace std;

/////////////////// Property Class //////////////////////

class Property
{
public:
    enum Operator
    {
        EQ,     // ==
        NEQ,    // !=
        GT,     // &gt;
        GTE,    // &gt;=
        LT,     // &lt;
        LTE,    // &lt;=
        SW,     // Starts With
    } mOperator;

    Property() {};
    Property(const int tag, Operator op)
            : mTag(tag), mOperator(op) {}
    virtual ~Property() {}
    virtual void* GetValue() = 0;
    virtual bool IsEqual(void* value) = 0;
    virtual bool Compare(void* value, Property::Operator op) = 0;
    virtual void Print() = 0;
    int mTag;
    bool operator&lt;(const Property &amp;property) const
    {
        return mTag &lt; property.mTag;
    }
};
struct PropertyPtrComp
{
    bool operator()(const std::tr1::shared_ptr&lt;Property&gt; lhs, const std::tr1::shared_ptr&lt;Property&gt; rhs) const
    {
        return lhs-&gt;mTag &lt; rhs-&gt;mTag;
    }
};

/////////////////// TypedProperty Class /////////////////

template&lt; typename T &gt;
class TypedProperty : public Property
{
public:
    TypedProperty (const int tag, const T&amp; value, Property::Operator op)
            : Property(tag, op), mValue(value) {}
    void* GetValue()
    {
        return &amp;mValue;
    }
    bool IsEqual(void* value)
    {
        return *((T*)value) == mValue;
    }
    bool Compare(void* value, Property::Operator op)
    {
        // cout &lt;&lt; "comparing " &lt;&lt; *((T*)value) &lt;&lt; " with " &lt;&lt; mValue &lt;&lt; endl;
        switch (op)
        {
           case Property::EQ:
               return *((T*)value) == mValue;
           case Property::NEQ:
               return *((T*)value) != mValue;
           case Property::GT:
               return mValue &gt; *((T*)value) ;
           case Property::LT:
               return mValue &lt; *((T*)value) ;
           case Property::SW:
           {
               if (typeid((T*)value) == typeid(string*))
               {
               // dont know what to do!
               //return ((string)mValue).compare(0, ((string*)value)-&gt;length(), (string)(*((string*)value)));
               }
           }
           default:
               return *((T*)value) == mValue;
        }
    }
    void Print()
    {
        cout &lt;&lt; "Tag: " &lt;&lt;  mTag &lt;&lt; ", Value: " &lt;&lt; mValue &lt;&lt; endl;
    }
    T mValue;
};

/////////////////////////////////////////////////////////

typedef std::tr1::shared_ptr&lt;Property&gt; PropertyPtr;

/////////////////// PropertyList Class /////////////////

class PropertyList
{
public:
    PropertyList() {};
    virtual ~PropertyList() {};
    template &lt;class T&gt;
    void Add(int tag, T value, Property::Operator op = Property::EQ)
    {
        PropertyPtr ptr(new TypedProperty&lt;T&gt;(tag, value, op));
        mProperties.insert(ptr);
    }
    void Print()
    {
        cout &lt;&lt; "-----------" &lt;&lt; endl;
        for (set&lt;PropertyPtr&gt;::iterator itr = mProperties.begin(); itr != mProperties.end(); itr++)
        {
            (*itr)-&gt;Print();
        }
    }
    set&lt;PropertyPtr, PropertyPtrComp&gt; mProperties;
};

//////////////////// Check Subset ///////////////////////
/*
 * Checks if subset is included in superset
 */
bool CheckSubset(set&lt;PropertyPtr, PropertyPtrComp&gt; &amp;superset, 
         set&lt;PropertyPtr, PropertyPtrComp&gt; &amp;subset)
{
    if (subset.size() &gt; superset.size() || subset.empty()) return false;
    typename set&lt;PropertyPtr&gt;::iterator litr = superset.begin();
    for (typename set&lt;PropertyPtr&gt;::iterator ritr = subset.begin(); ritr != subset.end();)
    {
        while (litr != superset.end())
        {
            PropertyPtr lProp = (PropertyPtr)*litr;
            PropertyPtr rProp = (PropertyPtr)*ritr;
            if (lProp-&gt;mTag == rProp-&gt;mTag)
            {
                if (lProp-&gt;Compare(rProp-&gt;GetValue(), rProp-&gt;mOperator))
                {
                    litr++;
                    break;
                }
                return false;
            }
            else
            {
                litr++;
            }
        }
        ritr++;
        if (litr == superset.end() &amp;&amp; ritr != subset.end()) return false;
    }
    return true;
}

int main()
{
    PropertyList properties;

    string s = "bye";

    properties.Add(1, "hello");
    properties.Add(2, 12);
    properties.Add(3, 34);
    properties.Add(4, "bye");

    properties.Print();

    PropertyList ruleSet1;
    ruleSet1.Add(2, 12, Property::EQ);
    ruleSet1.Add(4, "bye", Property::EQ);

    ruleSet1.Print();

    if(CheckSubset(properties.mProperties, ruleSet1.mProperties)) 
    cout &lt;&lt; "RuleSet1 verified!" &lt;&lt; endl;   // &lt;&lt;&lt;&lt; should be printed
    else
        cout &lt;&lt; "RuleSet1 NOT verified!" &lt;&lt; endl; 


    PropertyList ruleSet2;
    string hel = "hel";
    ruleSet2.Add(1, hel, Property::SW);
    ruleSet2.Add(2, 13, Property::NEQ);

    ruleSet2.Print();

    if (CheckSubset(properties.mProperties, ruleSet2.mProperties)) 
        cout &lt;&lt; "RuleSet2 verified!" &lt;&lt; endl;   // &lt;&lt;&lt;&lt; should be printed
    else
        cout &lt;&lt; "RuleSet2 NOT verified!" &lt;&lt; endl;


}
</code></pre>
