[bikeshed] Anyone have strong feelings about always putting `template <...>` on its own line?

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).

Examples of the current behavior:

+1

Have you got any statistics for the current state of LLVM with respect
to this formatting issue? If something is already the overwhelmingly
common style (& it's not a case where it used to be the style, the
style has been updated, and nothing has been migrated yet) then just
make clang-format agree with reality - this doesn't require a
discussion or bikeshed.

It's not overwhelming, but the preponderance seems to be towards putting it
on its own line (the exceptions are usually small trait specializations
like isPodLike). I give some rough numbers here <
http://thread.gmane.org/gmane.comp.compilers.llvm.devel/63378> (and see
Daniel's reply). Daniel is open to changing it, but asked me to gather some
more opinions.

-- Sean Silva

Have you got any statistics for the current state of LLVM with respect
to this formatting issue? If something is already the overwhelmingly
common style (& it's not a case where it used to be the style, the
style has been updated, and nothing has been migrated yet) then just
make clang-format agree with reality - this doesn't require a
discussion or bikeshed.

It's not overwhelming, but the preponderance seems to be towards putting it
on its own line (the exceptions are usually small trait specializations like
isPodLike). I give some rough numbers here
<http://thread.gmane.org/gmane.comp.compilers.llvm.devel/63378>

Fair enough - could we draw any further stylistic conclusions that
could motivate clang-format? If the entire definition of the template
fits on one line is it pretty consistent that it's defined on the one
line rather than split? What about template declarations, if any?

As a rough count, there are at least "hundreds" of cases where it changes
previously existing template definitions onto one line (i.e., they would
fit on one line but they weren't put on one line); this is more than the
total number of one-line definitions. To obtain a lower bound on the cited
"hundreds", I clang-format'd everything and then looked for just diff
chunks similar to:

-template <typename T>
-class ImmutableList {
+template <typename T> class ImmutableList {

$ cd llvm/
$ clang-format -i **/*.cpp **/*.h
$ git diff | grep -B2 '^+template' | egrep -B1 '^-(struct|class)' | grep
'^-template' | wc -l
287
# For comparison
$ git grep '^\s*template' -- '*.cpp' '*.h' | wc -l
2011

$ cd clang/
$ clang-format -i **/*.cpp **/*.h
$ git diff | grep -B2 '^+template' | egrep -B1 '^-(struct|class)' | grep
'^-template' | wc -l
396
# For comparison
$ git grep '^\s*template' -- '*.cpp' '*.h' | wc -l
6713

Outside of clang's test/ directory, there are a really tiny number of
one-line template definitions in clang:
$ cd clang/
$ git grep -E '^\s*template.*(class|struct).*{' -- lib include | wc -l
60

My general feel is that template declarations are usually one-lined in
existing code, but it seems that it is about half and half:
$ git grep -E '^ *template *<[^>]*> *(class|struct) [A-Za-z0-9_]+;' | wc -l
78
$ git grep -A1 -E '^ *template' | egrep -- '- *(struct|class)
[A-Za-z0-9_]+;' | wc -l
72

-- Sean Silva

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 would not like this change.

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).

There are innumerable other such cases. I don't know that this in and of
itself is an important goal. Personally, I favor compactness and brevity of
reading the code slightly over this. I'm sure others will have different
opinions and valuations. I'm not sure there is a significant consensus
behind this particular issue.

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.

It's all in the trade offs you're willing to make. There are several things
in clang-format today that will attempt a significantly different layout of
code in order to minimize the number of lines required even though it only
works when things happen to fit within 80 columns. I think those are still
worth having because often, things fit within 80 columns! =D

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.

I, as a reviewer, would not ask you to change it. I can't recall i single
review where this has come up. I don't think this alone is a good
motivation.

I'll point out that while you give an extreme example in one direction,
there are extreme examples in the other direction as well:

template <int N> template <int M> struct my_trait_a : true_type {};
template <> template <> struct my_trait_a<1, 2> : false_type {};
template <> template <> struct my_trait_a<2, 3> : false_type {};
template <> template <> struct my_trait_a<3, 4> : false_type {};
template <> template <> struct my_trait_a<4, 5> : false_type {};

I don't really relish these constructs consuming 3x the number of lines.

Both of these are extreme cases, and they trade off differently. I think
for the common case neither solution is bad, and the current behavior
consumes slightly fewer lines of code. I think that's a reasonable stance
and would vote to keep it.

>
>
>
>>
>>
>> Have you got any statistics for the current state of LLVM with respect
>> to this formatting issue? If something is already the overwhelmingly
>> common style (& it's not a case where it used to be the style, the
>> style has been updated, and nothing has been migrated yet) then just
>> make clang-format agree with reality - this doesn't require a
>> discussion or bikeshed.
>
>
> It's not overwhelming, but the preponderance seems to be towards putting
> it
> on its own line (the exceptions are usually small trait specializations
> like
> isPodLike). I give some rough numbers here
> <http://thread.gmane.org/gmane.comp.compilers.llvm.devel/63378>

Fair enough - could we draw any further stylistic conclusions that
could motivate clang-format? If the entire definition of the template
fits on one line is it pretty consistent that it's defined on the one
line rather than split? What about template declarations, if any?

As a rough count, there are at least "hundreds" of cases where it changes
previously existing template definitions onto one line (i.e., they would fit
on one line but they weren't put on one line); this is more than the total
number of one-line definitions.

No doubt - I'm just curious whether there's some internal
logic/consistency that we've not discussed. If you're claiming that
they are essentially "random" in the choice of wrap or no-wrap (in the
cases that would be affected by clang-format if code were reformatted
with it & clang-format chose one or the other as the default) then,
sure, flip a coin & go with it.

To obtain a lower bound on the cited
"hundreds", I clang-format'd everything and then looked for just diff chunks
similar to:

-template <typename T>
-class ImmutableList {
+template <typename T> class ImmutableList {

$ cd llvm/
$ clang-format -i **/*.cpp **/*.h
$ git diff | grep -B2 '^+template' | egrep -B1 '^-(struct|class)' | grep
'^-template' | wc -l
287
# For comparison
$ git grep '^\s*template' -- '*.cpp' '*.h' | wc -l
2011

$ cd clang/
$ clang-format -i **/*.cpp **/*.h
$ git diff | grep -B2 '^+template' | egrep -B1 '^-(struct|class)' | grep
'^-template' | wc -l
396
# For comparison
$ git grep '^\s*template' -- '*.cpp' '*.h' | wc -l
6713

Outside of clang's test/ directory, there are a really tiny number of
one-line template definitions in clang:
$ cd clang/
$ git grep -E '^\s*template.*(class|struct).*{' -- lib include | wc -l
60

Yeah, none of the style choices should include evidence from test code
- we write it completely differently.

My general feel is that template declarations are usually one-lined in
existing code, but it seems that it is about half and half:
$ git grep -E '^ *template *<[^>]*> *(class|struct) [A-Za-z0-9_]+;' | wc -l
78
$ git grep -A1 -E '^ *template' | egrep -- '- *(struct|class)
[A-Za-z0-9_]+;' | wc -l
72

Again, precluding test code, are there any discernable differences
between cases that are one line versus multiline? (some consistent
choice being made that could be enshrined in clang-format (or even a
consistent choice that is beyond the understanding of clang-format -
that's still helpful to know))

Not as far as I can tell.

-- Sean Silva