Most companies use [a newline for functions and same line for if]
FWIW I've never seen that style in use.
it happened to me out of exhaustion from having to spend so much time modifying so many places
That was just an example, so “it’s obvious” isn’t really a rebuttal. I was trying to figure out in release-mode (no break-point support) in which of the many places it could break from several loops, and I got sloppy after the 15th time I had to put a print (loose description of actual event—numbers and motivations may have been changed to protect their identities).
Yes, it is usually obvious, which is why I only missed one spot out of 16.
But that really took a lot of my time and was simply unnecessary.
Not to mention that in 16 places I had to waste more time placing braces that should have already been there. It takes more time to re-format existing code than to code it correctly in the first place.
As I said before, in 20 years of C++ I've not run into that bug, so the anecdote doesn't sway me Silly bugs from being tired and making repetitive changes sloppily happen everywhere. A good static analyzer excels at pointing out those kinds of bugs
Adding braces to an un-braced line/block is one key press in my IDE.
I spend more time reading code than writing it, so that's what I'm considering here -- I'm not trying to optimize typing speed. But now you're arguing that it's too hard to press a key to add missing braces when modifying code
Decisions based on subjective feelings cannot be correct or incorrect.
Why is it that we are against singletons and globals/statics (variables and classes/member functions) because they promote the idea of the author forcing him- or her- self into having “only one” (among other reasons), but when the author says, “There will only ever be one statement after this if,” we are just like, “Yeah, whatever, sounds good”?
Come on. That's a tad dramatic. I made you press a key, not refactor the entire code-base after performing an exhausting dependency analysis and redesigning the application's core architecture.
What is the argument for omitting braces?
Real-estate? Then why not:
if(count == students) break;
Or even better:
if(count == students) { break; }
Is it supposedly “faster to type because less typing”?
When typing braces is an automatic non-thought process, typing them always is never slower than considering whether you need them or not and omitting them accordingly.
What’s the win?
As above, I don't think there's a win in this particular part of a style debate for any side. It's purely style, to make the reader comfortable. I personally find this style comfortable to read, so that's the win. And yeah, I do use one-liners (usually without the braces) like in your first code-block there, when they happen to be the most readable option.
e.g. A random function from some personal code for allocating in a segmented stack:
u8* Scope::Alloc( uint size, uint align )
{
for(;;)
{
if( alloc->Align(align ? align : 16) )
{
u8* data = alloc->Alloc(size);
if( data )
return data;
}
OnOutOfMemory(align + size);
}
}
Opening braces moved up a line -- I just don't like it. It looks sloppy and less readable to me.
u8* Scope::Alloc( uint size, uint align ) {
while(1) {
if( alloc->Align( align ? align : 16 ) ) {
u8* data = alloc->Alloc( size );
if( data ) {
return data;
}
}
OnOutOfMemory( align + size );
}
}
Always using braces, even for one-liners, and padding out the ternary -- eh, it's ok, but looks unnecessarily bloated to me now... I find it less readable.
uint8_t* CScope::Alloc( unsigned int size, unsigned int align )
{
align = align
? align
: 16;
do
{
if(_alloc->Align(align))
{
uint8_t* data = _alloc->Alloc(size);
if(data)
{
return data;
}
}
OnOutOfMemory( align + size );
} while(1);
}
Maybe you want your opening braces on the same line, but also want the extra whitespace that you'd get from dedicating a line to each brace, and more! Maybe you also believe in half-tabs, and have banned ternaries and multiple exit points. Hey, I won't judge if you find this more readable. I have seen code like this before....
uint8_t*
CScope::Alloc
( unsigned int size,
unsigned int align )
{
uint8_t* data;
if( align == 0 ) {
align = 16;
}
retry:
if( m_alloc->Align(align) ) {
data = m_alloc->Alloc(size);
if( data ) { goto success; }
}
OnOutOfMemory( align + size );
goto retry;
success:
return data;
}
I find the top one the most readable. Others will disagree. That's to be expected from a stylistic choice. There's not many concrete objective arguments either way. As others have said, the most important thing is consistency, so I write in whatever style the rest of the codebase is using.
n.b. I also use u8 instead of uint8_t, and uint instead of unsigned int in that code. There's a lot of objective arguments against making your own typedefs like that, but I subjectively find them to help readability a lot. There's also 4 ways to write an infinite loop there -- I won't judge any of them, except the goto
Personally, I hate the brace-on-the-same-line-as-the-keyword style, as I like to be able to scan vertically to pair up braces. Having the start/end braces horizontally offset robs me of that nice little sanity check. As an objective complaint, that's about as weak as the people-might-python-indent complaint though
However, in Lua for example, instead of "{" we have "then"/"do" and instead of "}" we have "end". So in a language like that, you could write:
if blah
then
doStuff()
end
but I do typically follow the idomatic style of:
if blah then
doStuff()
end
...as I subjectively find that to be more readable.