title: shared_ptr<T> to shared_ptr<T const> and vector<T> to vector<T const>
body: <p>I'm trying to define a good design for my software which implies being careful about read/write access to some variables. Here I simplified the program for the discussion. Hopefully this will be also helpful to others. :-)</p>
  
  <p>Let's say we have a class X as follow:</p>
  
  <pre><code>class X {
      int x;
  public:
      X(int y) : x(y) { }
      void print() const { std::cout &lt;&lt; "X::" &lt;&lt; x &lt;&lt; std::endl; }
      void foo() { ++x; }
  };
  </code></pre>
  
  <p>Let's also say that in the future this class will be subclassed with X1, X2, ... which can reimplement <code>print()</code> and <code>foo()</code>. (I omitted the required <code>virtual</code> keywords for simplicity here since it's not the actual issue I'm facing.)</p>
  
  <p>Since we will use polymorphisme, let's use (smart) pointers and define a simple factory:</p>
  
  <pre><code>using XPtr = std::shared_ptr&lt;X&gt;;
  using ConstXPtr = std::shared_ptr&lt;X const&gt;;
  
  XPtr createX(int x) { return std::make_shared&lt;X&gt;(x); }
  </code></pre>
  
  <p>Until now, everything is fine: I can define <code>goo(p)</code> which can read and write <code>p</code> and <code>hoo(p)</code> which can only read <code>p</code>.</p>
  
  <pre><code>void goo(XPtr p) {
      p-&gt;print();
      p-&gt;foo();
      p-&gt;print();
  }
  
  void hoo(ConstXPtr p) {
      p-&gt;print();
  //    p-&gt;foo(); // ERROR :-)
  }
  </code></pre>
  
  <p>And the call site looks like this:</p>
  
  <pre><code>    XPtr p = createX(42);
  
      goo(p);
      hoo(p);
  </code></pre>
  
  <p><strong>The shared pointer to X (<code>XPtr</code>) is automatically converted to its const version (<code>ConstXPtr</code>)</strong>. Nice, it's exactly what I want!</p>
  
  <p>Now come the troubles: I need a heterogeneous collection of <code>X</code>. My choice is a <code>std::vector&lt;XPtr&gt;</code>. (It could also be a <code>list</code>, why not.)</p>
  
  <p>The design I have in mind is the following. I have two versions of the container: one with read/write access to its elements, one with read-only access to its elements.</p>
  
  <pre><code>using XsPtr = std::vector&lt;XPtr&gt;;
  using ConstXsPtr = std::vector&lt;ConstXPtr&gt;;
  </code></pre>
  
  <p>I've got a class that handles this data:</p>
  
  <pre><code>class E {
      XsPtr xs;
  public:
      E() {
          for (auto i : { 2, 3, 5, 7, 11, 13 }) {
              xs.emplace_back(createX(std::move(i)));
          }
      }
  
      void loo() {
          std::cout &lt;&lt; "\n\nloo()" &lt;&lt; std::endl;
          ioo(toConst(xs));
  
          joo(xs);
  
          ioo(toConst(xs));
      }
  
      void moo() const {
          std::cout &lt;&lt; "\n\nmoo()" &lt;&lt; std::endl;
          ioo(toConst(xs));
  
          joo(xs); // Should not be allowed
  
          ioo(toConst(xs));
      }
  };
  </code></pre>
  
  <p>The <code>ioo()</code> and <code>joo()</code> functions are as follow:</p>
  
  <pre><code>void ioo(ConstXsPtr xs) {
      for (auto p : xs) {
          p-&gt;print();
  //        p-&gt;foo(); // ERROR :-)
      }
  }
  
  void joo(XsPtr xs) {
      for (auto p: xs) {
          p-&gt;foo();
      }
  }
  </code></pre>
  
  <p>As you can see, in <code>E::loo()</code> and <code>E::moo()</code> I have to do some conversion with <code>toConst()</code>:</p>
  
  <pre><code>ConstXsPtr toConst(XsPtr xs) {
      ConstXsPtr cxs(xs.size());
      std::copy(std::begin(xs), std::end(xs), std::begin(cxs));
      return cxs;
  }
  </code></pre>
  
  <p>But that means copying everything over and over.... :-/</p>
  
  <p>Also, in <code>moo()</code>, which is const, I can call <code>joo()</code> which will modify <code>xs</code>'s data. Not what I wanted. Here I would prefer a compilation error.</p>
  
  <p>The full code is available at <a href="http://ideone.com/DRv4RD" rel="noreferrer">ideone.com</a>.</p>
  
  <p><strong>The question is: is it possible to do the same but without copying the vector to its const version? Or, more generally, is there a good technique/pattern which is both efficient and easy to understand?</strong></p>
  
  <p>Thank you. :-)</p>