<div dir="ltr"><div>tl;dr If there are no objections I'd like to change clang-format's LLVM style to always put `template <...>` on its own line. I think it's a general code-layout consistency win and avoids some cases where trivial code changes result in significant formatting differences (see the last example).</div>
<div><br></div><div><div>Examples of the current behavior:</div><div><br></div><div>--------------</div><div><div>template <class ELFT></div><div>class ELFState {</div><div><br></div><div>clang-format's to:</div>
<div><br></div><div>template <class ELFT> class ELFState {</div></div><div>--------------<br></div><div><br></div><div>--------------<br></div><div><div>template <class T></div><div>static size_t vectorDataSize(const std::vector<T> &Vec) {</div>
<div><br></div><div>clang-format's to:</div><div><br></div><div>template <class T> static size_t vectorDataSize(const std::vector<T> &Vec) {</div></div><div>--------------<br></div><div><br></div><div>
Pathological example:</div><div>--------------<br></div><div><div><div>template <class T, size_t N, int X></div><div>template <class U></div><div>Foo<T, N, X>::bar(U Uv) {</div><div> for (unsigned i = 0, e = Uv.size(); i != e; ++i)</div>
<div> use(i);</div><div>}</div></div><div><br></div><div>clang-format's to:</div><div><br></div><div><div>template <class T, size_t N, int X> template <class U> Foo<T, N, X>::bar(U Uv) {</div><div>
for (unsigned i = 0, e = Uv.size(); i != e; ++i)</div><div> use(i);</div><div>}</div><div><br></div><div>while the completely minor modification s/int/unsigned/ results (due to line length restrictions) in clang-format agreeing with the former layout:</div>
<div><br></div><div><div>template <class T, size_t N, unsigned X></div><div>template <class U></div><div>Foo<T, N, X>::bar(U Uv) {</div><div> for (unsigned i = 0, e = Uv.size(); i != e; ++i)</div><div> use(i);</div>
<div>}</div></div></div><div>--------------</div></div></div><div><br class="">I would prefer that two pieces of code with similar logical structure to be similarly formatted, as much as reasonable, and I think that always breaking on template declarations is reasonable.<br>
</div><div><br></div><div>clang-format has an option for this (`<span style="font-size:13px;color:rgb(0,0,0);font-family:arial,sans-serif">AlwaysBreakTemplateDeclaration</span><span style="font-size:13px;color:rgb(0,0,0);font-family:arial,sans-serif">s`), but we don't have it enabled currently for LLVM style. Daniel Jasper informs me that the current setting is a carry-over from before the setting was introduced, where it was effectively always "false" (the current setting for LLVM style).</span><br>
</div><div><br></div>I hate to bring up such a microscopic issue, but I find myself manually fixing clang-format's behavior with LLVM style when it comes to putting `template <...>` on its own line, since TBH I feel like a reviewer would ask me to change it.<div>
<br></div><div>At a basic level I think what bothers me about it is that it breaks useful invariants while reading code:</div><div>- A class or struct declaration always has `class` or `struct` as the first non-whitespace character on the line (also helpful when grepping).</div>
<div style>- When reading code, you can seek past the template by just going down to the next line starting at the same indentation. If the `template <...>` gets put on the same line, then you have to "parse through it" to find what is actually being declared.</div>
<div style>- There is a single way to lay out `template <...>`. With the current setting, clang-format will still put the `template <...>` on its own line in a lot of cases due to line length restrictions, but in others it will be put onto the same line. Hence in some cases you can "skip down past it" and in others you have to "parse through it", but worst of all you have to detect which it is when reading the code.</div>
<div style><span style="font-size:13px;color:rgb(0,0,0);font-family:arial,sans-serif"><br></span></div><div style><span style="font-size:13px;color:rgb(0,0,0);font-family:arial,sans-serif">-- Sean Silva</span></div></div>