title: c++11 combining std::tuple and std::tie for efficient ordering
body: <p>I am fairly new to std::tuple and std::tie.  I need a way to efficiently order structs according to a left to right ordering of comparisons.  For this reason, I chose to use the <a href="http://en.cppreference.com/w/cpp/utility/tuple/make_tuple" rel="nofollow">std::make_tuple</a> and <a href="http://en.cppreference.com/w/cpp/utility/tuple/tie" rel="nofollow">std::tie</a> types for custom ordering a StructA in the <a href="http://coliru.stacked-crooked.com/a/a882b8ae062e42ac" rel="nofollow">live example</a> provided.  The tuple approach provides built in equivalence comparisons starting from left to right which is ideal for <em>LessThanComparable</em> element ordering for a std::sort with an accompanying lambda comparator (for which I show 3 examples).  </p>
  
  <p>The problem is that as far as I am aware, <a href="http://en.cppreference.com/w/cpp/utility/tuple/make_tuple" rel="nofollow">std::make_tuple</a> makes <a href="http://vexorian.blogspot.com/2013/07/more-about-c11-tuples-tie-and-maketuple.html" rel="nofollow">inefficient copies</a> of the tuple elements, and I was wondering if there was some way to combine std::make_tuple with std::tie as I tried to do with my 3rd comparator - which failed (otherwise its output would look like the first output ordering).  </p>
  
  <p>In my specific example I cannot use <a href="http://en.cppreference.com/w/cpp/utility/tuple/tie" rel="nofollow">std::tie</a> directly as I need to use a temporary as the 1st element in my tuple.</p>
  
  <p>The output is as follows</p>
  
  <pre><code>Order[mPath.filename(), elem1, intVal]
  ======================================
  "/zoo/dir1/filename.txt" - nameA1 - 1
  "/tmp/dir1/filename.txt" - nameA1 - 3
  "/fad/dir1/filename.txt" - nameA1 - 4
  
  Order[mPath, elem1, intVal]
  ======================================
  "/fad/dir1/filename.txt" - nameA1 - 4
  "/tmp/dir1/filename.txt" - nameA1 - 3
  "/zoo/dir1/filename.txt" - nameA1 - 1
  
  Order[mPath.filename(), elem1, intVal]
  ======================================
  "/fad/dir1/filename.txt" - nameA1 - 4
  "/tmp/dir1/filename.txt" - nameA1 - 3
  "/zoo/dir1/filename.txt" - nameA1 - 1
  </code></pre>
  
  <p>I was expecting that the 3rd set of outputs would be identical to the first or alternatively if someone could tell me how to correctly mix inefficient std::tuples with efficient std::ties</p>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;string&gt;
  #include &lt;vector&gt;
  #include &lt;tuple&gt;
  #include &lt;boost/filesystem.hpp&gt;
  
  struct StructA {
      boost::filesystem::path mPath;
      std::string elem1;
      int intVal;
  };
  
  template&lt;typename CharT, typename Traits&gt;
  std::basic_ostream&lt;CharT, Traits&gt;&amp; 
  operator&lt;&lt;(std::basic_ostream&lt;CharT, Traits&gt;&amp; os, StructA const&amp; sa) {
      return os &lt;&lt; sa.mPath &lt;&lt; " - " &lt;&lt; sa.elem1 &lt;&lt; " - " &lt;&lt; sa.intVal &lt;&lt; std::endl;
  }
  
  
  int main()
  {
      std::vector&lt;StructA&gt; aStructs = {
          {"/zoo/dir1/filename.txt", "nameA1", 1}, 
          {"/fad/dir1/filename.txt", "nameA1", 4}, 
          {"/tmp/dir1/filename.txt", "nameA1", 3}
      };    
  
      std::cout &lt;&lt; "Order[mPath.filename(), elem1, intVal]" &lt;&lt; std::endl;
      std::cout &lt;&lt; "======================================" &lt;&lt; std::endl;
      std::sort(aStructs.begin(), aStructs.end(),
          [](const StructA&amp; lhs, const StructA&amp; rhs){
              return std::make_tuple(lhs.mPath.filename(), lhs.elem1, lhs.intVal) &lt; 
                  std::make_tuple(rhs.mPath.filename(), rhs.elem1, rhs.intVal);
          });
  
      // print reordered structs
      std::copy(aStructs.begin(), aStructs.end(),
          std::ostream_iterator&lt;StructA&gt;(std::cout, ""));        
  
      std::cout &lt;&lt; std::endl;
  
      std::cout &lt;&lt; "Order[mPath, elem1, intVal]" &lt;&lt; std::endl;
      std::cout &lt;&lt; "======================================" &lt;&lt; std::endl;
      std::sort(aStructs.begin(), aStructs.end(),
          [](const StructA&amp; lhs, const StructA&amp; rhs){
              return std::tie(lhs.mPath, lhs.elem1, lhs.intVal) &lt; 
                  std::tie(rhs.mPath, rhs.elem1, rhs.intVal);
          });
  
      // print reordered structs
      std::copy(aStructs.begin(), aStructs.end(),
          std::ostream_iterator&lt;StructA&gt;(std::cout, ""));
  
      std::cout &lt;&lt; std::endl;
  
      std::cout &lt;&lt; "Order[mPath.filename(), elem1, intVal]" &lt;&lt; std::endl;
      std::cout &lt;&lt; "======================================" &lt;&lt; std::endl;
      std::sort(aStructs.begin(), aStructs.end(),
          [](const StructA&amp; lhs, const StructA&amp; rhs){
              // attempt at efficiency - but not quite right
              return lhs.mPath.filename() &lt; rhs.mPath.filename() &amp;&amp; 
                  std::tie(lhs.elem1, lhs.intVal) &lt; std::tie(rhs.elem1, rhs.intVal);
          });
  
      // print reordered structs
      std::copy(aStructs.begin(), aStructs.end(),
          std::ostream_iterator&lt;StructA&gt;(std::cout, ""));
  }
  </code></pre>