std::string product{"not worked"};
Searching for "curly braces C++ string" is not really productive.
I'm also curious what
[&](job& my_job) { }
means.
It's the same as std::string product; product = "not worked";
[&](job& my_job) { } is a lambda expression. & is capturing the variable by reference. my_job is the parameter being passed which is a pointer of type job.
Please check https://en.cppreference.com/w/cpp/language/lambda and https://docs.microsoft.com/en-us/cpp/cpp/lambda-expressions-... for more.
It's not exactly the same. The original called the converting constructor std::string::string(const char*). Your example calls the std::string default constructor, then the assignment std::string::operator=(const char*). Maybe you didn't mean literally the same, but where trying to illustrate the rough meaning, but the parent commenter said they were familiar with older versions of C++ so I think they'd already be familiar with converting constructors.
It might be more enlightening to say that all of the following are equivalent:
std::string product{"not worked"};
std::string product("not worked");
std::string product = "not worked";
std::string product = std::string("not worked");
(I'm 90% sure about the last one but can't find documentation for it at the moment.) None of them call the copy constructor std::string::string(const std::string&) or copy assignment operator std::string::operator=(const std::string&), although in older versions of the C++ standard the last two required that the relevant assignment operators (std::string::operator=(const char*) and std::string::operator=(const std::string&) respectively) to be accessible even though it wasn't called.For other combinations of types, these different syntaxes are not equivalent. For example, uniform initialisation (with the braces) won't allow narrowing conversions, such as short to int or double to float.
Not a C++ person, so please forgive my ignorance, but what is the difference between the above and sth. like:
std::string product = "not worked";
or std::string product("not worked");
(Are these even legal C++ statements and, if not, why not? ;-))Brace initialization has an advantage in that it allows you to initialize compound values, like containers and structs, even if they're nested:
std::map<int, std::string> m = { // nested list-initialization
{1, "a"},
{2, {'a', 'b', 'c'} },
{3, s1}
};
Ref: https://en.cppreference.com/w/cpp/language/list_initializati... https://en.cppreference.com/w/cpp/language/aggregate_initial...From the POV of the standard, those are different kinds of initializations. C++ has like 12 different ways of initializing variables, and the differences are quite confusing, but in practical terms in my experience I never had to care too much beside making sure native types are initialized to some specified value.
You can probably find some talks on YouTube talking about the initializations of c++, and 1h30m is probably not enought to cover all the details :')
std::string product;
product = "not worked";
i.e., separate declaration and initialization, as suggested by the grand-parent?https://en.cppreference.com/w/cpp/language/direct_initializa... https://en.cppreference.com/w/cpp/language/move_assignment
What are examples of situations where the other pattern would be preferable?
otherwise you should really avoid it.
The second one is a direct initialization, invoking corresponding constructor.
The first one first invokes default constructor and then copy or move assignment depending on rvalueness of the arg.
The second one is a lambda (which, if you're not familiar with the term, are anonymous functions/functors); the entries in the initial brackets define the captured variables (if any), and whether they're captured by reference (with ampersand) or by value (without).
[1] https://en.cppreference.com/w/cpp/language/list_initializati...
Uniform initialization is great, except for the unfortunate interaction with initialized_lists (yes, we can't have nice things), but if you do not have an initializer_list constructor in your class you do not have to worry.
Why do you say this when you can explicitly see I specifically made sure to avoid claiming it is in fact a forced cast, and instead I said it is kind of like a forced cast? Clearly I meant something other than that it was actually a forced cast, right?
> if you do not have an initializer_list constructor in your class you do not have to worry.
Which is precisely an example of my point about it being problematic. How would you go about this when you don't know everything about a class? Like, say, in a template? And how do you prevent your code from silently breaking if a class you use later adds an initializer_list constructor?
> Uniform initialization is great
I disagree. It's awful. It's just a minor cosmetic change (which we can call an "improvement" for the sake of argument, though I think that's also dubious and the syntax is just ugly) that introduces pitfalls in the actual semantics of your program. That's not a great trade-off; it's a terrible one.
std::int64_t i64 { 44 * 44 * 44 }; std::int8_t i8 = i64; // perfectly fine std::int8_t i8_2 { i64 }; // refuses to narrow the int
uniform initialization resolves lots of headaches, like T() being ambiguous at times with functions, narrowing, etc.
With T() being ambiguous, you can already syntactically disambiguate. With extra parentheses or whatever other construct the case may warrant. As people have been doing all these years. Again, it's just a minor syntactic inconvenience.
The second one is a lambda function / closure over my_job.
>[&](job& my_job) { } A lambda function that takes in a reference to job!
C++ has definitely evolved but the package management is still difficult unlike cargo!
For personal projects, vcpkg with manifests is a breeze to use.
If you make a point to always use the newest features, where there is a choice, and really put the type system to work for you, programs generally run right the first time, once the compiler is satisfied. In the past ten years I have spent more time filing compiler bug reports than debugging C++ memory usage errors.
It is amazing how many people are all up-to-date on what is new. I think people who complain about C++ on HN must be complaining about a much older version of the language.
Even Android NDK and some subsystems are good examples of this second C++ flavour.