title: Is there a better way to generic print containers in C++20/C++23?
body: <p>I use the following code to print generic C++ containers and exclude strings (thanks to <a href="https://stackoverflow.com/a/1154683/2599610">this</a> SO answer).</p>
  <pre><code>#include &lt;iostream&gt;
  #include &lt;vector&gt;
  
  template &lt;typename T,
            template &lt;typename ELEM, typename ALLOC = std::allocator&lt;ELEM&gt;&gt;
            class Container&gt;
  std::ostream &amp;operator&lt;&lt;(std::ostream &amp;out, const Container&lt;T&gt; &amp;container) {
    out &lt;&lt; &quot;[&quot;;
    bool first = true;
    for (const auto &amp;elem : container) {
      if (first)
        first = false;
      else
        out &lt;&lt; &quot;, &quot;;
      out &lt;&lt; elem;
    }
    return out &lt;&lt; &quot;]&quot;;
  }
  
  int main() {
    std::vector&lt;std::vector&lt;int&gt;&gt; v{{1, 2}, {3, 4}};
    std::cout &lt;&lt; v &lt;&lt; &quot;\n&quot;;
    return 0;
  }
  </code></pre>
  <p>Which prints the 2d vector correctly</p>
  <pre><code>[[1, 2], [3, 4]]
  </code></pre>
  <p>And does not mess with outputting strings. Is there a cleaner (concept-based?) way to write the template in C++20 or C++23?</p>