> It’s been a while now, and at least in my experience so far Go and Rusts choice of not having special constructors really simplifies a lot.
This take makes no sense. Think about it: you're saying that not having the compiler do any work for you "really simplifies things a lot". Cool, so you have to explicitly declare and define all constructors. That's ok. But think about it, doesn't C++ already offer you that option from the very start? I mean, you are talking about a feature in C++ that is not mandatory or required, and was added just to prevent those programmers who really really wanted to avoid writing boilerplate code to lean on the compiler in and only in very specific corner cases. If for any reason you want the compiler to do that work for you, you need to be mindful of the specific conditions where you can omit your own member functions. For the rest of the world, they can simply live a normal life and just add them.
How is this complicated?
Complaining that special member functions make obvious things less simple is like complaining that English is not simple jus because you can find complicated words in a dictionary. Yes, you can make it complicated if that's what you want, but there is nothing forcing you to overcomplicate things, is there?
You're mistaken. Rust does not require you to define all constructors. Rust does not have constructors.
All structs in Rust must be initialized using brace syntax, e.g. `Foo { bar: 1, baz: "" }`. This is commonly encapsulated into static functions (e.g. `Foo::new(1, "")`) that act similarly to constructors, but which are not special in any way compared to other functions. This avoids a lot of the strangeness in C++ that arises from constructors being "special" (can't be named, don't have a return type, use initializer list syntax which is not used anywhere else).
This combined with mandatory move semantics means you also don't have to worry about copy constructors or copy-assignment operators (you opt into copy semantics by deriving from Clone and explicitly calling `.clone()` to create a copy, or deriving from Copy for implicit copy-on-assign) or move constructors and move-assignment operators (all non-Copy assignments are moves by default).
It's actually rather refreshing, and I find myself writing a lot of my C++ code in imitation of the Rust style.
Your post starts with the flawed assumption that you have to define constructors in Rust, and then your own wall of text (ironically longer than mine) about avoiding boilerplate which doesn't apply to Rust. I'm not sure you understood my point.
> Just to further illustrate what I'm saying, are you really trying to say that (...)
If you read what I wrote you'll notice I was pointing out the absurdity of claiming that being forced to write each and every single factory method/constructor is somehow better and simpler than allowing the compiler to write them for us for trivia classes but still having the compiler step off when we opt to write each and every single factory method/constructor ourselves.
- As a junior programmer, it made the language harder to learn. Language complexity increases super-linearly as each new feature has rules of interaction with several existing features
- Although one eventually learns to avoid the anti-features, you cannot control the actions of others. These features meant to help save keystrokes are happily employed every day, producing hard to read code
Particularly when writing library code for other to use or when maintaining large codebases shared by hundreds of engineers, my experience is that complex features in the language end up used by junior engineers or require consideration in API design.
> As a junior programmer, it made the language harder to learn.
Can you elaborate on your opinion? I mean, I don't think that argument makes any sense. You're talking about an optional feature that, under very specific circumstances, you can get the compiler to fill in for you default implementations for factory methods/constructors.
As a junior developer, it should be very clear to you that if you want to call a function, including copy constructor or copy assignment operators, you need to define them first. Is that too much of a burden to place on a junior developer?
> Although one eventually learns to avoid the anti-features (...)
There are none of those, and obviously special member functions don't pose a problem to anyone.
> Particularly when writing library code for other to use or when maintaining large codebases shared by hundreds of engineers, my experience is that complex features in the language end up used by junior engineers or require consideration in API design.
I don't think you have a good grasp on the subject. I've worked on C++ libraries shared by hundreds of engineers, and API design was always from the start the primary concern. This is not a function of seniority: it's the very basics of writing modular code intended to be consumed by third parties.
Still, special member functions are the very least of anyone's concerns because anyone remotely competent in this domain knows very well that the public interface needs to be explicitly designed to support or reject specific types of uses, and the decision of whether a component could/should be copied/moved is tied to the component's architecture and semantics.
This take makes no sense. Think about it: you're saying that not having the compiler do any work for you "really simplifies things a lot". Cool, so you have to explicitly declare and define all constructors. That's ok. But think about it, doesn't C++ already offer you that option from the very start? I mean, you are talking about a feature in C++ that is not mandatory or required, and was added just to prevent those programmers who really really wanted to avoid writing boilerplate code to lean on the compiler in and only in very specific corner cases. If for any reason you want the compiler to do that work for you, you need to be mindful of the specific conditions where you can omit your own member functions. For the rest of the world, they can simply live a normal life and just add them.
How is this complicated?
Complaining that special member functions make obvious things less simple is like complaining that English is not simple jus because you can find complicated words in a dictionary. Yes, you can make it complicated if that's what you want, but there is nothing forcing you to overcomplicate things, is there?