Overload binary operator for vector I want to be able to construct and fill a vector of bytes using a stream (binary shift) operators. So I overloaded operator &lt;&lt; (...).

Here is the code I want to write :

using ByteVector = std::vector&lt;uint8_t&gt;;

void send_message(MessageId id, std::vector&lt;ByteVector&gt; parameters);

void foo()
{
    std::string str = "A string object";
    int bar = 42;

    ByteVector baz = {0x42, 0x13, 0x37};

    send_message(MessageId::COMMAND, {
        ByteVector() &lt;&lt; str,
        ByteVector() &lt;&lt; bar,
        ByteVector() &lt;&lt; baz
    });
}


I started by adding the following operator overloads :

ByteVector &amp; operator &lt;&lt; (ByteVector &amp; bv, const std::string &amp; str);
ByteVector &amp; operator &lt;&lt; (ByteVector &amp; bv, uint8_t byte);
ByteVector &amp; operator &lt;&lt; (ByteVector &amp; bv, const ByteVector &amp; bv2);
ByteVector &amp; operator &lt;&lt; (ByteVector &amp; bv, int value);


They were working well for following use case:

ByteVector bv;
std::string str = "Never gonna give you up";
bv &lt;&lt; str;


But not the for previous example where my compiler (clang) shows the following error:

error: invalid operands to binary expression ('ByteVector' (aka 'vector&lt;unsigned char&gt;') and 'const std::string' (aka 'const basic_string&lt;char, char_traits&lt;char&gt;, allocator&lt;char&gt; &gt;'))

note: candidate function not viable: expects an l-value for 1st argument
ByteVector &amp; operator &lt;&lt; (ByteVector &amp; bv, const std::string &amp; str);
             ^
note: candidate function not viable: expects an l-value for 1st argument
ByteVector &amp; operator &lt;&lt; (ByteVector &amp; bv, uint8_t byte);
             ^

note: candidate function not viable: expects an l-value for 1st argument
ByteVector &amp; operator &lt;&lt; (ByteVector &amp; bv, const ByteVector &amp; bv2);
             ^

note: candidate function not viable: expects an l-value for 1st argument
ByteVector &amp; operator &lt;&lt; (ByteVector &amp; bv, int value);
             ^


I didn't really understand the error. I think the compiler want's to use the ByteVector() in ByteVector() &lt;&lt; something  as a rvalue (ByteVector &amp;&amp;).

So I added the following operator overload:

template&lt;typename T&gt;
ByteVector &amp;&amp; operator &lt;&lt; (ByteVector &amp;&amp; bv, T data)
{
    return std::move(bv &lt;&lt; data);
}


This overload solve the compiler error. But I would like to know if my implementation is good and optimal in terms of good practice, memory usage and efficiency.
Instead of returning an rvalue reference, it's better to return bv by value:

template&lt;typename T&gt;
ByteVector operator&lt;&lt; (ByteVector &amp;&amp; bv, T data)
{
    return bv &lt;&lt; data;
}


C++ compilers perform return value optimisation, which means that the return value won't be copied in this case.



An alternative approach is to ignore the advice not to subclass standard library containers, and implement your operators as member methods.  That will remove the need to overload for rvalue types, and I believe it's safe to do so for this use.