title: Common interface for derived classes using SFINAE
body: <p>I want to add (dynamic) properties to a C++ class, which can be of several types (e.g. <code>float</code>, <code>int</code>, <code>bool</code>). Depending on their value type, different controls should be shown in the interface.</p>
  
  <p>To do this, I created a simple Property class using SFINAE for the <code>type()</code> function:</p>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;type_traits&gt;
  
  template &lt;class T&gt;
  class Property
  {
  public:
    enum Type {
      Undefined = -1,
      Int,
      Float,
      Bool,
    };
  
    explicit Property(const std::string&amp; name) : name_(name) { }
  
    const std::string&amp; name() const { return name_; }
  
    // specialization for floating point type() getter
    template&lt;class U = T,
             typename std::enable_if&lt;std::is_floating_point&lt;U&gt;::value&gt;::type* = nullptr&gt;
    Type type() const {
      return Type::Float;
    }
  
    // specialization for integer type() getter
    template&lt;class U = T,
             typename std::enable_if&lt;std::is_integral&lt;U&gt;::value&gt;::type* = nullptr&gt;
    Type type() const {
      return Type::Int;
    }
  
    // specialization for boolean type() getter
    template&lt;class U = T,
             typename std::enable_if&lt;std::is_same&lt;U, bool&gt;::value&gt;::type* = nullptr&gt;
    Type type() const {
      return Type::Bool;
    }
  
  private:
    std::string name_;
    T value_;
  };
  
  int main() {
    // this works
    auto fProp = new Property&lt;float&gt;("float property");
    std::cout &lt;&lt; fProp-&gt;type() &lt;&lt; std::endl;
  }
  </code></pre>
  
  <p>So far, this works reasonably well. Now, the problems comes when I want to store several of these properties in a vector. For this, I created a common interface, and changed the class accordingly:</p>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;type_traits&gt;
  #include &lt;vector&gt;
  
  class IProperty
  {
    // common interface for all typed Property&lt;T&gt;'s
  public:
    enum Type {
      Undefined = -1,
      Int,
      Float,
      Bool,
    };
  
    virtual const std::string&amp; name() const = 0;
  };
  
  template &lt;class T&gt;
  class Property : public IProperty
  {
  public:
    explicit Property(const std::string&amp; name) : name_(name) { }
  
    const std::string&amp; name() const { return name_; }
  
    // specialization for floating point type() getter
    template&lt;class U = T,
             typename std::enable_if&lt;std::is_floating_point&lt;U&gt;::value&gt;::type* = nullptr&gt;
    Type type() const {
      return Type::Float;
    }
  
    // specialization for integer type() getter
    template&lt;class U = T,
             typename std::enable_if&lt;std::is_integral&lt;U&gt;::value&gt;::type* = nullptr&gt;
    Type type() const {
      return Type::Int;
    }
  
    // specialization for boolean type() getter
    template&lt;class U = T,
             typename std::enable_if&lt;std::is_same&lt;U, bool&gt;::value&gt;::type* = nullptr&gt;
    Type type() const {
      return Type::Bool;
    }
  
  private:
    std::string name_;
    T value_;
  };
  
  int main() {
  
    // works
    auto fProp = new Property&lt;float&gt;("float property");
    std::cout &lt;&lt; fProp-&gt;type() &lt;&lt; std::endl;
  
    std::vector&lt;IProperty*&gt; properties;
    properties.push_back(fProp);
  
    // error: 'class IProperty' has no member named 'type'
    for (auto iprop : properties) {
      std::cout &lt;&lt; iprop-&gt;type() &lt;&lt; std::endl;  
    }
  
  }
  </code></pre>
  
  <p>As you see, I can't call the <code>type()</code> method because it's not defined for the <code>IProperty</code> class. I tried defining a pure virtual <code>IProperty::type()</code>, but of course this doesn't work with the templated derived class.</p>
  
  <p>What are my options here?</p>