title: Why does static_cast not use the conversion operator to pointer to const?
body: <p>From my wrapper class <code>Pointer&lt;Base&gt;</code> I'd like to only return pointers to const: <code>Base const *</code>.<br>
  When casting <code>Pointer&lt;Base&gt;</code> to <code>Derived const *</code> I get a compile error:</p>
  
  <blockquote>
    <p>error C2440: 'static_cast': 'Pointer' can not be converted to 'const Derived *'</p>
  </blockquote>
  
  <p>(translated from german VS2012)</p>
  
  <pre><code>struct Base { };
  
  struct Derived : public Base { };
  
  template &lt;typename T&gt;
  class Pointer {
  public:
      Pointer(T *t = nullptr) : p(t) { }
  
      //operator T*() { return p; }
      operator T const *() const { return p; }
  
      template &lt;typename U&gt;
      inline U staticCast() const { return static_cast&lt;U&gt;(d); }
  
  private:
      T *p;
  };
  
  int main(int argc, char *argv[]) {
      Derived d;
      Pointer&lt;Base&gt; p(&amp;d);
  
      Derived const *pd = static_cast&lt;Derived const *&gt;(p);
  }
  </code></pre>
  
  <p>If I enable the conversion <code>operator T*() { return p; }</code> it works.</p>
  
  <p>Why doesn't <code>static_cast</code> use the const conversion operator?</p>
  
  <p>Or more specifically, since</p>
  
  <pre><code>Derived const *pd = static_cast&lt;Derived const *&gt;(static_cast&lt;Base const *&gt;(p));
  </code></pre>
  
  <p>works:</p>
  
  <p>Why can <code>static_cast</code> implicitly cast to <code>Base *</code>, but not to <code>Base const *</code>, even though the latter is sufficient for the cast target type?</p>
  
  <hr>
  
  <p><a href="https://en.cppreference.com/w/cpp/language/static_cast" rel="nofollow noreferrer">The standard says</a>:</p>
  
  <blockquote>
    <p>If there is an implicit conversion sequence from expression to new_type, or if overload resolution for a direct initialization of an object or reference of type new_type from expression would find at least one viable function, then static_cast(expression) returns the imaginary variable Temp initialized as if by new_type Temp(expression);, which may involve <strong>implicit conversions</strong>, a call to the constructor of new_type or <strong>a call to a user-defined conversion operator</strong>.</p>
  </blockquote>
  
  <p>[Emphasis by me]</p>
  
  <hr>
  
  <p><strong>Workaround</strong></p>
  
  <p>Since this seems like a VisualStudio bug, I will use a workaround instead by means of a templated member function <code>staticCast()</code> (see sample code above), to be used like this:</p>
  
  <pre><code>Derived const *pd = p.staticCast&lt;Derived const *&gt;();
  </code></pre>
  
  <p>To allow only casts to <code>U const *</code>, use SFINAE:</p>
  
  <pre><code>template &lt;typename U&gt;
  struct is_pointer_to_const
  {
      static const bool value = std::is_pointer&lt;U&gt;::value
              &amp;&amp; std::is_const&lt;typename std::remove_pointer&lt;U&gt;::type &gt;::value;
  };
  
  template &lt;typename U&gt;
  inline U staticCast(typename std::enable_if&lt;is_pointer_to_const&lt;U&gt;::value &gt;::type* = 0) const
  { return static_cast&lt;U&gt;(d); }
  
  template &lt;typename U&gt;
  inline U staticCast(typename std::enable_if&lt;!is_pointer_to_const&lt;U&gt;::value &gt;::type* = 0) const
  { static_assert(false, "Type is not a pointer to const"); return U(); }
  </code></pre>