title: Extending the functionality of std::vector<uint8_t> - namespace, composition or inheritance?
body: <p>Very often I need to provide a <code>uint8_t</code> array to some third-party library. Usually the third-party library asks for a <code>uint8_t*</code>, together with a length argument. Generally I use a <code>std::vector&lt;uint8_t&gt;</code> and use its <code>data()</code> and <code>size()</code> methods to get this information which works a treat. Now I've often found myself wanting to create this <code>vector&lt;uint8_t&gt;</code> using the <code>&lt;&lt;</code> operator, similar to how <code>std::stringstream</code> works, for example:</p>
  <pre><code>uint8_t first = 8;
  uint8_t second = 3;
  
  std::vector&lt;uint8_t&gt; raw;
  raw &lt;&lt; first
      &lt;&lt; second;
  </code></pre>
  <p>Often I need to mix integers of different sizes - a few one-byte header bytes, then one four-byte value, then a one-byte crc. This <code>&lt;&lt;</code> overload automatically takes care of this, for example:</p>
  <pre><code>uint32_t value = 0;
  
  std::vector&lt;uint8_t&gt; raw;
  raw &lt;&lt; value;
  
  int sz = raw.size(); // sz = 4
  </code></pre>
  <p>The <code>operator&lt;&lt;</code> function would look somewhat like the following. Keep in mind that in order to split up into individual bytes I'd either define multiple <code>operator&lt;&lt;</code> overloads, one for each type, or make a <code>std::is_arithmetic</code> restricted template. I'm not showing this for simplicity.</p>
  <pre><code>std::vector&lt;uint8_t&gt;&amp; operator &lt;&lt; (std::vector&lt;uint8_t&gt;&amp; msg, uint8_t const&amp; value)
  {
      msg.push_back(value);
      return msg;
  }
  </code></pre>
  <p>Now I obviously want to restrict this functionality. Not every <code>std::vector&lt;uint8_t&gt;</code> should have this functionality. One solution would be to define the <code>operator&lt;&lt;</code> in namespace <code>serial</code> and whenever the functionality is needed write <code>using namespace serial;</code> in the required scope. While not a bad solution, I still think this is a little confusing. In the same scope I may have a different <code>std::vector&lt;uint8_t&gt;</code> for which this functionality is not needed.</p>
  <p>I'd ideally create a new type, <code>Message</code> which allows for this functionality so the code becomes:</p>
  <pre><code>Message msg1;
  msg1 &lt;&lt; 4; // OK, I've defined this
  uint8_t* ptr1 = msg1.data(); // get pointer to first element - needs to be defined in the Message class.
  
  std::vector&lt;uint8_t&gt; msg2;
  msg2 &lt;&lt; 4; // not OK, not part of std::vector&lt;uint8_t&gt;
  uint8_t* ptr2 = msg2.data(); // get pointer to first element, fine as it's in std::vector
  </code></pre>
  <h3>Composition</h3>
  <p>Now I could use composition to make this struct, like this:</p>
  <pre><code>struct Message
  {
      std::vector&lt;uint8_t&gt; raw;
  };
  </code></pre>
  <p>However that means that whenever you want to call a method of the vector (<code>size()</code>, <code>data()</code>, <code>begin()</code>, etc...) you need to call <code>msg.raw.size()</code>, <code>msg.raw.data()</code>, <code>msg.raw.begin()</code> which isn't particularly elegant (in my opinion). Obviously you can add functions to the Message struct that replicate the original functionality, like:</p>
  <pre><code>size_t size() const { return raw.size() };
  size_t size() const noexcept { return raw.size() };
  </code></pre>
  <p>However given the size of std::vector that's a lot of functions, not to mention you'd have to change them when std::vector changes. I don't necessary need all functions that std::vector has to offer, but where to draw the line?</p>
  <h3>Inheritance</h3>
  <p>As far as I know - you do not, ever, inherit from standard types. Then I saw <a href="https://stackoverflow.com/questions/46233041/type-alias-and-operator-overloading-with-ostream-iterator-results-in-invalid-o">this</a> answer by Richard Hodges, who seems to have a pretty good reputation, give this as a solution to a different question:</p>
  <pre><code>// Edge is now a type, in the global namespace...
  struct Edge : std::pair&lt;VertexName, VertexName&gt; {
      using std::pair&lt;VertexName, VertexName&gt;::pair;
  };
  </code></pre>
  <p>Does this mean I could do the following?</p>
  <pre><code>struct Message : std::vector&lt;uint8_t&gt; {
      using std::vector&lt;uint8_t&gt;::vector;
  };
  
  Message msg1;
  msg1 &lt;&lt; 8; // works (provided I define the operator&lt;&lt; as shown above for Message)
  int sz = msg1.size(); // works as Message is a std::vector, result: 4
  
  std::vector&lt;uint8_t&gt; msg2;
  msg2 &lt;&lt; 8; // doesn't work, as intended
  </code></pre>
  <p>What about if I want to add a variable to it, so it becomes:</p>
  <pre><code>enum class Endian
  {
      lsb,
      msb
  };
  
  struct Message : std::vector&lt;uint8_t&gt;
  {
      using std::vector&lt;uint8_t&gt;::vector;
      Endian m_endian;
  };
  </code></pre>
  <p>Concrete question: can I do the second approach as it suits my needs best, or will I be in trouble as I inherit from std::vector? Any advice on the best approach would be very much appreciated.</p>