title: Semantics for wrapped objects: reference/value by default via std::move/std::ref
body: <p>In recent times I am using often a natural idiom I "discovered" in C++11 that is that wrapped object can automatically hold reference when this is possible. The main question here will be about the comparison with the behavior of this "idiom" to other behaviors in the standard (see below).</p>
  
  <p>For example:</p>
  
  <pre><code>template&lt;class T&gt;
  struct wrap{
      T t;
  };
  template&lt;class T&gt; wrap&lt;T&gt; make_wrap(T&amp;&amp; t){
      return wrap{std::forward&lt;T&gt;(t)};
  }
  </code></pre>
  
  <p>In this way for the code</p>
  
  <pre><code>double a = 3.14
  double const c = 3.14
  </code></pre>
  
  <p>I get,</p>
  
  <pre><code>typeid( make_wrap(3.14) ) --&gt; wrap&lt;double&gt;
  typeid( make_wrap(a) ) --&gt; wrap&lt;double&amp;&gt;
  typeid( make_wrap(c) ) --&gt; wrap&lt;double const&amp;&gt;
  </code></pre>
  
  <p>which if I am careful (with dangling references) I can handle pretty well. And if I want to <strong>avoid</strong> references I do:</p>
  
  <pre><code>typeid( make_wrap(std::move(a)) ) --&gt; wrap&lt;double&gt; // noref
  typeid( make_wrap(std::move(c)) ) --&gt; wrap&lt;double const&gt; // noref
  </code></pre>
  
  <p>So, this behavior seems natural in C++11. </p>
  
  <p>Then I went back to <code>std::pair</code> and <code>std::make_pair</code> and somehow I expected that they used this new seemly natural behavior, but apparently the behavior is "more traditional". So for example:</p>
  
  <pre><code>typeid( std::make_pair(3.14, 3.14) ) --&gt; std::pair&lt;double, double&gt;
  typeid( std::make_pair(a, a) ) --&gt; std::pair&lt;double, double&gt; // noref
  typeid( std::make_pair(c, c) ) --&gt; std::pair&lt;double, double&gt; // noref
  </code></pre>
  
  <p>and <strong>for</strong> references:</p>
  
  <pre><code>typeid( std::make_pair(std::ref(a), std::ref(a) ) ) --&gt; std::pair&lt;double&amp;, double&amp;&gt; // ref
  typeid( std::make_pair(std::ref(c), std::ref(c) ) ) --&gt; std::pair&lt;double const&amp;, double const&amp;&gt; // const ref
  </code></pre>
  
  <p>This is documented here: <a href="http://en.cppreference.com/w/cpp/utility/pair/make_pair" rel="nofollow">http://en.cppreference.com/w/cpp/utility/pair/make_pair</a></p>
  
  <p>As you see the two behaviors are "opposite", in some sense <code>std::ref</code> is the complement to <code>std::move</code>. So both behaviors are equally flexible at the end, but it seems to me that the <code>std::make_pair</code> behavior is more difficult to implement and maintain.</p>
  
  <p>The question is: <strong>Is the current behavior of <code>std::make_pair</code> of discarding references by default just a backward compatibility issue?</strong> because some historical expectation? or there is a deeper reason that still exists in C++11?</p>
  
  <p>As it is, it looks like this <code>std::make_pair</code> behavior is much more difficult to implement as it requires specialization for <code>std::ref</code> (<code>std::reference_wrapper</code>) and <code>std::decay</code> and even seems unnatural (in the presence of "C++11 move"). At the same time even if I decide to keep using the first behavior I am affraid that the 
  behavior will be pretty unexpected with respect to current standards, even in C++11.</p>
  
  <p>In fact I am pretty fond of the first behavior, to the point that the elegant solution maybe to change the prefix <code>make_something</code> for something like <code>construct_something</code> in order to mark the difference in behavior. (<strong>EDIT</strong>: one of the comments suggested to look at <code>std::forward_as_tuple</code>, so another name convention could be <code>forward_as_something</code>). Regarding naming, the situation is not clear cut when pass-by-value, pass-by-ref is mixed in the construction of the object.</p>
  
  <hr>
  
  <p><strong>EDIT2:</strong> This is an edit just to answer a @Yakk's about being able to "copy" wrap object with different ref/value properties. This is not part of the question and it is just experimental code:</p>
  
  <pre><code>template&lt;class T&gt;
  struct wrap{
      T t;
      // "generalized constructor"? // I could be overlooking something important here
      template&lt;class T1 = T&gt; wrap(wrap&lt;T1&gt; const&amp; w) : t(std::move(w.t)){}
      wrap(T&amp;&amp; t_) : t(std::move(t)){} // unfortunately I now have to define an explicit constructor
  };
  </code></pre>
  
  <p>This seems to allow me to copy between unrelated types <code>wrap&lt;T&amp;&gt;</code> and <code>wrap&lt;T&gt;</code>:</p>
  
  <pre><code>auto mw = make_wrap(a);
  wrap&lt;double const&amp;&gt; copy0 =mw;
  wrap&lt;double&amp;&gt; copy1 = mw; //would be an error if `a` is `const double`, ok
  wrap&lt;double&gt; copy2 = mw;
  </code></pre>
  
  <hr>
  
  <p><strong>EDIT3:</strong> This edit is to add a concrete example in which the traditional reference deduction can fail depend on a "protocol". The example is based in the use of Boost.Fusion.</p>
  
  <p>I discovered how much the implicit conversion from reference to value can depend on the convention. For example the good old Boost.Fusion follows the STL convention of </p>
  
  <blockquote>
    <p>Fusion's generation functions (e.g. make_list) by default stores the
    element types as plain non-reference types.</p>
  </blockquote>
  
  <p>However that relies in the exact "type" that tags the reference, in the case of Fusion was the <code>boost::ref</code> and in the case of <code>make_pair</code> is... <code>std::ref</code>, a completely unrelated class. So, currently, given</p>
  
  <pre><code>double a;
  </code></pre>
  
  <p>the type of <code>boost::fusion::make_vector(5., a )</code> is <code>boost::fusion::vector2&lt;double, double&gt;</code>. Ok, fine.</p>
  
  <p>And the type of <code>boost::fusion::make_vector(5., boost::ref(a) ) ) is</code>boost::fusion::vector2`. Ok, as documented.</p>
  
  <p>However, surprise, since Boost.Fusion was not written with C++11 STL's in mind we get:
  <code>boost::fusion::make_vector(5., std::ref(a) ) )</code> is of type <code>boost::fusion::vector2&lt;double, std::reference_wrapper&lt;double const&gt; &gt;</code>. Surprise!</p>
  
  <p>This section was to show that the current STL behavior depends on a protocol (e.g. what class to use to tag references), while the other (what I called "natural" behavior) using <code>std::move</code> (or more exactly rvalue casting) doesn't depend on a protocol, but it is more native to the (current) language.</p>