title: Interface reference to local implementation
body: <p>Please consider the following code:</p>
  
  <pre><code>struct A
  {
      virtual ~A() {}
      virtual int go() = 0;
  };
  
  struct B : public A { int go() { return 1; } };
  
  struct C : public B { int go() { return 2; } };
  
  int main()
  {
      B b;
      B &amp;b_ref = b;
  
      return b_ref.go();
  }
  </code></pre>
  
  <p>Under GCC 4.4.1 (using <code>-O2</code>), the call to <code>B::go()</code> gets inlined (ie., no virtual dispatch happens). That means the compiler acknowledges <code>a_ref</code> indeed points to a <code>B</code> type variable. A <code>B</code> reference can be used to point to a <code>C</code>, but the compiler is smart enough to foresee this is not the case, so it totally optimizes away the function call, inlining the function.</p>
  
  <p><em>Great!</em> That's an incredible optimization.</p>
  
  <p>But, then, why doesn't GCC do the same in the following case?</p>
  
  <pre><code>struct A
  {
      virtual ~A() {}
      virtual int go() = 0;
  };
  
  struct B : public A { int go() { return 1; } };
  
  struct C : public B { int go() { return 2; } };
  
  int main()
  {
      B b;
      A &amp;b_ref = b;
  
      return b_ref.go(); // B::go() is not inlined here, and a virtual dispatch is issued
  }
  </code></pre>
  
  <p>Any ideas? What about other compilers? Is this kind of optimization common? (I'm very new into this kind of compiler insight, so I'm curious)</p>
  
  <p>If the second case worked I could create some really great templates, like these:</p>
  
  <pre><code>template &lt;typename T&gt;
  class static_ptr_container
  {
  public:
      typedef T st_ptr_value_type;
  
      operator T *() { return &amp;value; }
      operator const T *() const { return &amp;value; }
  
      T *operator -&gt;() { return &amp;value; }
      const T *operator -&gt;() const { return &amp;value; }
  
      T *get() { return &amp;value; }
      const T *get() const { return &amp;value; }
  
  private:
      T value;
  };
  
  template &lt;typename T&gt;
  class static_ptr
  {
  public:
      typedef static_ptr_container&lt;T&gt; container_type;
      typedef T st_ptr_value_type;
  
      static_ptr() : container(NULL) {}
      static_ptr(container_type *c) : container(c) {}
  
      inline operator st_ptr_value_type *() { return container-&gt;get(); }
      inline st_ptr_value_type *operator -&gt;() { return container-&gt;get(); }
  
  private:
      container_type *container;
  };
  
  template &lt;typename T&gt;
  class static_ptr&lt;static_ptr_container&lt;T&gt;&gt;
  {
  public:
      typedef static_ptr_container&lt;T&gt; container_type;
      typedef typename container_type::st_ptr_value_type st_ptr_value_type;
  
      static_ptr() : container(NULL) {}
      static_ptr(container_type *c) : container(c) {}
  
      inline operator st_ptr_value_type *()  { return container-&gt;get(); }
      inline st_ptr_value_type *operator -&gt;()  { return container-&gt;get(); }
  
  private:
      container_type *container;
  };
  
  template &lt;typename T&gt;
  class static_ptr&lt;const T&gt;
  {
  public:
      typedef const static_ptr_container&lt;T&gt; container_type;
      typedef const T st_ptr_value_type;
  
      static_ptr() : container(NULL) {}
      static_ptr(container_type *c) : container(c) {}
  
      inline operator st_ptr_value_type *() { return container-&gt;get(); }
      inline st_ptr_value_type *operator -&gt;() { return container-&gt;get(); }
  
  private:
      container_type *container;
  };
  
  template &lt;typename T&gt;
  class static_ptr&lt;const static_ptr_container&lt;T&gt;&gt;
  {
  public:
      typedef const static_ptr_container&lt;T&gt; container_type;
      typedef typename container_type::st_ptr_value_type st_ptr_value_type;
  
      static_ptr() : container(NULL) {}
      static_ptr(container_type *c) : container(c) {}
  
      inline operator st_ptr_value_type *() { return container-&gt;get(); }
      inline st_ptr_value_type *operator -&gt;() { return container-&gt;get(); }
  
  private:
      container_type *container;
  };
  </code></pre>
  
  <p>These templates could be used to avoid virtual dispatch in many cases:</p>
  
  <pre><code>// without static_ptr&lt;&gt;
  void func(B &amp;ref);
  
  int main()
  {
      B b;
      func(b); // since func() can't be inlined, there is no telling I'm not
               // gonna pass it a reference to a derivation of `B`
  
      return 0;
  }
  
  // with static_ptr&lt;&gt;
  void func(static_ptr&lt;B&gt; ref);
  
  int main()
  {
      static_ptr_container&lt;B&gt; b;
      func(b); // here, func() could inline operator-&gt;() from static_ptr&lt;&gt; and
               // static_ptr_container&lt;&gt; and be dead-sure it's dealing with an object
               // `B`; in cases func() is really *only* meant for `B`, static_ptr&lt;&gt;
               // serves both as a compile-time restriction for that type (great!)
               // AND as a big runtime optimization if func() uses `B`'s
               // virtual methods a lot -- and even gets to explore inlining
               // when possible
  
      return 0;
  }
  </code></pre>
  
  <p>Would it be practical to implement that? (and don't go on saying it's a micro-optimization because it may well be a huge optimization..)</p>
  
  <p>-- edit</p>
  
  <p>I just noticed the problem with <code>static_ptr&lt;&gt;</code> has nothing to do with the problem I exposed. The pointer type is kept, but it still doesn't inline. I guess GCC just doesn't go as deep as needed to find out static_ptr_container&lt;>::value is not a reference nor pointer. Sorry about that. But the question still remains unanswered.</p>
  
  <p>-- edit</p>
  
  <p>I've worked out a version of <code>static_ptr&lt;&gt;</code> that actually works. I've changed the name a bit, also:</p>
  
  <pre><code>template &lt;typename T&gt;
  struct static_type_container
  {
      // uncomment this constructor if you can't use C++0x
      template &lt;typename ... CtorArgs&gt;
      static_type_container(CtorArgs ... args)
              : value(std::forward&lt;CtorArgs&gt;(args)...) {}
  
      T value; // yes, it's that stupid.
  };
  
  struct A
  {
      virtual ~A() {}
      virtual int go() = 0;
  };
  
  struct B : public A { int go() { return 1; } };
  
  inline int func(static_type_container&lt;Derived&gt; *ptr)
  {
      return ptr-&gt;value.go(); // B::go() gets inlined here, since
                              // static_type_container&lt;Derived&gt;::value
                              // is known to be always of type Derived
  }
  
  int main()
  {
      static_type_container&lt;Derived&gt; d;
      return func(&amp;d); // func() also gets inlined, resulting in main()
                       // that simply returns 1, as if it was a constant
  }
  </code></pre>
  
  <p>The only weakness is that the user has to access <code>ptr-&gt;value</code> to get the actual object. Overloading <code>operator -&gt;()</code> doesn't work in GCC. Any method returning a reference to the actual object, if it it's inline, breaks the optimization. What a pity..</p>