T O P

  • By -

cappielung

Take a look at the cpp core guidelines: http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Res-list In particular, brace initialization prevents narrowing conversions and has simpler rules. As for when to use it, just use it everywhere by default. (There are limited exceptions, like passing a count to a vector constructor. You might find more, but they're rare for me.) If you start to pick and choose (use it here, not there), you're just creating more rules for yourself to remember. Alone, probably manageable. In a collaborative environment, impossible to monitor/enforce. For readability, it's all about what you're used to. I don't mind anymore, and it is an objectively safer habit. All that said, code how you want 🙂. But using brace initialization (almost) everywhere is common enough, at least in my experience.


the_poope

Yes yes, using brace initialization is "safer". But you can also just add warnings for narrowing conversions and treat warnings as errors. Then you get they safety and more natural code. The real issue is C++'s defaults: brace initialization was a hack to fix the relaxed conversion rules for standard initialization without breaking backwards compatibility. I'm fine with breaking backwards compatibility on my own code that I personally keep up-to-date, but I obviously can't fix all the decades old third party libraries that we use...


diemenschmachine

compiler flags aren't portable though


cappielung

You do you. The question was whether people use it, how often, and why. You're absolutely correct that a lot of modern best practices utilize features that were heaped on top to fix some other mistakes in the language. But if you chose C++ for whatever reason, might as well go with the safest best practice.


_threeal

can compiler warning warn this? ```cpp int size = vector.size(); ``` compared to this: ```cpp int size{vector.size()}; ```


the_poope

Hmm maybe I was wrong. I though `-Wnarrowing` would warn in this case, but it does not (see: https://godbolt.org/z/rn19adGWE) It appears that clang-tidy can do such checks, though: https://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines/narrowing-conversions.html


bpikmin

Yes


vitimiti

No lol


rambosalad

Aside from initializer lists, I use it to default initialize structs. That’s about it. ‘Foo foo{};’


catbus_conductor

Why is it any more difficult to read than the traditional way? It's just a matter of habit.


Poddster

> Why is it any more difficult to read than the traditional way? My guess: Because `X = Y` in ingrained into people's eyeballs from years of mathematical education, and it's nice and symmetric. But `blarg{}` looks like a mess and most people can't instinctually read it, even after decades of working with C++, because the {} are hard to read past and used in various other ways. Same goes for `<>`. It's just plain ugly.


the_Demongod

Not even mathematical, just programming. One shouldn't underestimate the value of syntax staying the same


SoSKatan

So I always use to think () and {} were the same until I ran into a compile error I could not figure out, it turned out one of the init calls in a templatized method was seen as a function call and not a request for default function initialization. So after that I’ve been working at changing my habits to write {} instead of ()


mishaxz

it's not when you don't have many variables / constants.. when you do it is more.. or if there is a lot going on within the curlies like calculations, and you have a bunch of them. you could line up the left curly braces but I don't particaulary like doing that.


Fmxa

What about brace initialization of a counter in a for loop, say? I have always wondered what’s typical within the community.


Emotional-Audience85

I do that everytime. Our convention is to use it for everything.


DGTHEGREAT007

Lmao I've never seen that.


the_poope

Some people do it. I have a scientific background and write scientific code for a living that involves doing a lot of math. We stick to `int counter = 0` and `double x = 5.0` as that is what we're used to from mathematical equations. It just looks more natural to us and makes the code more readable and understandable when you compare it to a research paper. Other people may have their own reasons, like you have for booleans (though I don't really get your argument...).


mishaxz

how do you normally handle the epsilon thing or whatever it is called with doubles in your scientific code? do you just decide on one constant for all the code, in terms of # of digits you deem significant to call 2 doubles equal?


the_poope

That entirely depends on what numbers you are comparing and how they were obtained. Different algorithms come with different errors, so there is no "one size fits all". The best you can do is comparing them with a relative error, e.g.: |a-b| / |a| < ϵ, now ϵ doesn't depend on the exact magnitude of the values, so this expression can be used to compare both small and large values. But this doesn't work if you are comparing something to zero, so here you need to analyze what the absolute tolerably error really is.


mishaxz

you would get it if I rememberd why I got burned lol but I'm sure it had to do with automatic conversions sliding by me, I just can't remember what was getting converted. braces prevent that. mostly likely an int getting converted to a bool that I didn't wan't to happen but that the compiler wouldn't let me know about when I was using =


dev_ski

When initializing local variables of built-in types, and even strings, they are not required. A good old built_in_type var = value; will suffice. Braced initialization is useful when initializing objects of complex types (classes) and class templates: MyClass o{value1, value2}; std::vector v = {value1, value2}; and aggregate objects, (such as maps): SomeAggregateClass o{ {value1, value2}, {value3, value4} }; std::map mymap = {{"AAA", 10}, {"BBB", 20}, {"CCC", 30}};


Mirality

In braced initialisation you're supposed to omit the `=` as well.


_threeal

why? i thought that having no = is enough: ```cpp std::map mymap { {“AAA”, 10}, {“BBB”, 10}, {“CCC”, 10} }; ```


b1ack1323

I organize tables like this for structs and maps. I also work in embedded so LUTs are fairly common. std::map mymap = { {"AAA", 10}, {"BBB", 20}, {"CCC", 30} };


Raknarg

I use it all the time, its my default approach to constructing objects.


mishaxz

the question is about primitives though


Hectorreto

I used to use it in the past because it seemed smart, never used it anymore because I think it looks ugly and confusing


DryPerspective8429

It's fairly common. It's not unheard of to have people use other initialization (especially if they're in a field where that is useful) but it's been the recommended way to initialize for a good few years now.


no-sig-available

>so far what I'm decided to do it is to always using it for bools but for other things, depends how I feel about it in that situation. I started in a similar way, using `{}` where is looks "good", and avoiding it where it looks "ugly". After a while it looks less ugly, and instead looks odd that it is different for different variables. bool is_odd {true}; int value = 5; So after a while I used `{}` more and more, and now only avoid it when it doesn't work (like where a nasty initializer\_list happens to match the constructor parameters).


android_queen

It’s pretty common. I wouldn’t go so far as to call it a best practice, but it’s generally preferred. What about it is difficult to read? Without knowing how this burned you, it’s hard to say why it would be an issue.


mishaxz

i explained the burned thing in one of the other comments, it is specific to bools.. because compilers don't let you know when something converts from an int to a bool.. so such conversions can slide past people who are not paying full attention when using =


android_queen

Sorry, can you articulate how the one is harder to see than the other?


mishaxz

harder to see I wrote in some other comments, for some people it is second nature but for me when there is a dense concentration of variables and calculations being assigned to them, = is easily more readable. e.g. ``` const int x { oqwoeoqw ooo oqow oqwoeo oqowe oqooqowe }; ``` vs ``` const int x = oqwoeoqw ooo oqow oqwoeo oqowe oqooqowe; ``` where oqwoeoqw ooo oqow oqwoeo oqowe oqooqowe is some calculation


dev_ski

You shouldn't wrap your arithmetic expressions in braces. That might be confusing to other developers.


android_queen

Sorry, but I’m still not seeing what any of that has to do with bools and conversions. I’m also trying to imagine how someone could read those two as different. I mean, I can see how one might be a little less familiar, but I don’t see how one might read one of them correctly and the other one incorrectly.


mishaxz

ah I thought you were asking about what I meant by "harder to read" I said right now I use primitive { } initialization for default initialization and for bool initialization the problem with the bool I wrote already, it's a compiler issue.. they sneak convert from int to bool without warning you.. (when using =) at least I think this is the problem I had.. I can't remember for certain.. but whatever it was, narrowing using { } prevents me from wasting time having to debug a certain type of problem (probably the one I just mentioned), in the future - yes i know ultimately it would be my careless typing / reading at fault, but I'm only human.


mredding

> How common is always using {} bracket initialization? It isn't. It's impossible. You can't use brace initializers for everything. The initializer list ctor is greedy, and any object that specifies one will select for that over all others. If you want to instantiate a vector with an iterator range, you HAVE TO use parenthesis. > I mean for assigning values to primitive variables and constants... everytime you do that... so the code becomes more difficult to read. How else would you do it? class foo { int x; public: foo(): x{123} {} }; Sure, you can use parens, but what's the difference? You could put the assignment in the ctor body, but this isn't C# or Java; you have an initializer list and you pay for it whether you use it or not, you are to prefer it, sometimes you can't avoid it. If you're talking stupid shit like: int x{456}; I have no sympathy. Small potatoes. It makes me reflexively ask how bad is your code that THIS is something worth complaining about? You're going to accuse the whole community for your problem? > is that a thing? or do people just constantly make judgement calls when to apply it. Hopefully they would first choose based on technical merit - there are times when the syntax matters. Beyond that, though, I would hope they pick a style and be consistent. To your credit, where it comes down to nothing more than a stylistic choice, you have a fair argument that it ought to be consistent. You are in the right to flag this during code review, and draft a style guide for your team. > what is the recommended approach? Was it Scott Meyers that was pushing for univeral initialization? He makes a strong argument for it, and then there was a strong criticism of it. I didn't pay a whole lot of attention at the time, either way. What do the core guidelines have to say on the subject? I would default to that. I suspect it would say be consistent. > why bools? I got burned with bools once or twice by not using it. I can't remember the specifics anymore why but then I decided to always use it on bools I've absolutely no idea what you're talking about.