5 ms·
In my view this author falls into the camp of people calling C++ a mess because it gives them too much control when they ask for it. One of his examples which h
by tines 8y ago
In my view this author falls into the camp of people calling C++ a mess because it gives them too much control when they ask for it. One of his examples which he calls "The Abyss":
#include <iostream>
struct A {
A(std::initializer_list<int> l) : i(2) {}
A(int i = 1) : i(i) {}
int i;
};
int main() {
A a1;
A a2{};
A a3(3);
A a4 = {5};
A a5{4, 3, 2};
std::cout << a1.i << " "
<< a2.i << " "
<< a3.i << " "
<< a4.i << " "
<< a5.i << std::endl;
}
which outputs:
1 1 3 2 2
he claims to be mysterious but is actually pretty reasonable.
In the case of:
a1: There is no initializer list in the variable declaration, so ctor 2 is called.
a2: An empty initializer list should reasonably behave like a default constructor, and a default constructor should be more efficient than processing an initializer_list, so ctor 2 is called. In general, the constructor with the matching number of arguments and correct types is preferred over initializer_list constructors. Makes sense, being able to specialize on number and type of arguments is more powerful than a design where a single initializer_list ctor invalidates all other ctors.
a3: No list, ctor 2 is called.
a4: Non-empty init list and no specialized non-init-list ctor, so ctor 1 is called.
a5: Several-variable init list and no overriding 3-variable constructor with matching types, therefore ctor 1 is called.
Complex? Maybe, but that's what you get with C++: very fine control of program semantics, benefit being expressive libraries. No other language fills this niche that I'm aware of.
I agree that C++ isn't a good language to teach in a CS 101 class. But no other single language is good either. The goal of CS 101 is to not make students give up before they get hooked, and that can happen because the material is too challenging or not challenging enough. For people in the former category, give them a scripting language and visual feedback, like Lua + Garrysmod. For the latter, give them assembly, haskell, C, C++ (teaching it like "C with templates" not "C with classes").
- ori_b 8y ago> Complex? Yes, but that's what you get with C++: Congrats on successfully summarizing the complaint. It's not mysterious, but it's gratuitously complex. And this is only variable initialization.
- jblow 8y agoIndeed. If just setting integers is this complicated, what do you expect to happen when you are trying to solve real problems?
- kllrnohj 8y agoThe parsing details can be complicated while the end result can be simple. Consider the actual C++ example that would be taught & used in practice: struct A { int i = 0; } int main() { A a; std::cout << a.i << std::endl; } Hey, look, done. And you only had to teach a single thing - default initialization. Which has an obvious & simple syntax. The int i is always initialized to 0, as intended, and it's in a single spot at the point of declaration. Now try doing that in C. Oh, wait, you can't. The closest you can get is this mess: struct A { int i; } const default_A = {0}; int main() { struct A a5 = default_A; printf("%d\n", a5.i); } Which requires you to know that you can declare a type & an instance of that type in a single statement, why that const is where it is and why that's important here, how braced initialization rules work, that you need to always remember to manually initialize to your default_A, and that %d means 'int'. And the compiler won't help you with any of this except for the %d part if you get it wrong.
- jstimpfle 8y ago> Which requires you to know that you can declare a type & an instance of that type in a single statement struct A { int i; }; const struct A default_A = { 0 }; Why didn't you try the obvious simple thing first? The whole undertaking is pointless in any case. Why would you need default values (i.e. templates for constructors) baked in? The only reasonable default value, sometimes, is all-zeroes (or all-ones...). Now, constant data (i.e. things that contain more useful information than just "it's the default because a real value is missing" -- and that aren't copied around pointlessly) is another case, and C's plain old value initializer syntax (as demonstrated above) serves it perfectly well.
- kllrnohj 8y ago
- xyzzyz 8y ago> a2: An empty initializer list should reasonably behave like a default constructor, and a default constructor should be more efficient than processing an initializer_list, so ctor 2 is called. Yes, initializer list with empty initializer list should behave same as empty constructor, and if it doesn’t, it’s really bad style. However, if both are defined, then if you are constructing an object with empty initializer list, the initializer list constructor should be called with an empty list as an argument, simple as that. That’s very logical and sensible semantics, so obviously C++ had to choose something different.
- tines 8y agoWhile it does sometimes seem like C++ does some things because of how much sense they don't make, I don't think this is one of those cases. Read the rest of the sentence you quoted and I think you'll find that the way C++ does it will make sense.
- xyzzyz 8y agoNo, that reasoning is unsatisfactory. It would explain why A a; or A a(21, 37) calls A(); and A(int p, int q); respectively despite presence of A(std::initializer_list<int> l), but the initializer list constructor should still be called when one writes A a{} and A a{21, 37}. That would be consistent and predictable.
- slavik81 8y agoBut a2 isn't an empty initializer list. A{} is the same as A(). You could use A{} even if there was no initializer list constructor. The squiggly brackets are from uniform initialization: a feature created to avoid the ambiguity between zero-argument constructors and zero-argument function declarations. Unfortunately, std::initializer_list created a new ambiguity, so it's only an initializer list if it doesn't match an existing constructor.
- slavik81 8y agostd::initializer_list was probably the greatest mistake made in modern C++, but you can mostly avoid the complexity it introduced just by not using it. You usually only encounter it when you are trying to use it, in which case it behaves as you'd expect.
- MikeLui 8y agoHi. I completely agree. C++ is there for very fine control and serves the purpose well (and is constantly adding more control, e.g. trivially relocatable). My biggest goal for a CS 101 class would just to build computational and critical thinking skills. I would love to just start off with peanut butter and jelly sandwiches[1]. As an engineering department, our students start with an engineering programming class that needs to also serve chemical, mechanical, civil, material, and biomedical engineers along with electrical and computer engineers(I hope I didn't leave anyone out). [1]: https://edtechmagazine.com/k12/article/2008/07/programming-and-pbj https://edtechmagazine.com/k12/article/2008/07/programming-a...
- forrestthewoods 8y agoC++ initialization is such a convoluted mess that CppCon was able to have an entire hour dedicated to "The Nightmare of Initialization in C++". https://www.youtube.com/watch?v=7DTlWPgX6zs https://www.youtube.com/watch?v=7DTlWPgX6zs C++ has a rigorous standard. There is no rule that wasn't added for a reason. Nor are there lines of code with which you can specify which rule it must follow. The path to hell is paved with good intentions. Just because each step is logical and defensible doesn't mean the end result isn't fire and brimstone. I believe that good things are more than the sum of their parts. You often hear this with respect to creative works like movies or games. I think it also applies to source code, language design, and much more. The flipside is that bad things are less than the sum of their parts. I've shipped games that fall into this category. C++ initialization has a LOT of parts. And I would strongly argue the end result is less than the sum of those parts.
- zanny 8y ago> it gives them too much control when they ask for it Rust gives you too much control when you ask for it, with unsafe blocks, cells, etc. C++ will stab you in the gut at random because you looked at it the wrong way. > But no other single language is good either. I had Python for my CS101, Java for 102, C for 201, and C++ for ~202. This was a decade ago now, but even then I thought it was a pretty good track. You learn fundamentals of computation in Python fully apart from the hardware warts, you get to taste what the corporate monotony many of you will be faced with for decades to weed out the chafe, then you get a dose of cold hard reality when its too late to turn back that it gets even worse.
- int_19h 8y agoThe problem with C++ that the article explores isn't that it's complex. It's that it's unnecessarily complex, and you could have a language with all that power (and then some, like say a proper macro facility) without so many warts. Indeed, Rust is a proof by example now. Of course, those warts were necessary for C++ to be successful back when it was introduced and competing against others, and therefore to its popularity today. And this popularity is just as much a part of C++ appeal as its power. But we can call them out for what they are, without trying to justify them.
- stonescarecrow 8y ago> An empty initializer list should reasonably behave like a default constructor True. But an empty initializer list should also behave like, you know, the constructor which uses an initializer list. C++ is in the unfortunate position of having to choose one behaviour or the other. Either choice is reasonable, but both can be confusing.