7 ms·
> In languages like C++ "verbose" means "specific and obvious" Whoa, no it doesn't. C++ is far more verbose than necessary for things like creating algebraic
by SamReidHughes 12y ago
> In languages like C++ "verbose" means "specific and obvious"
Whoa, no it doesn't. C++ is far more verbose than necessary for things like creating algebraic datatypes or really creating any types.
- jjoonathan 12y agoOr looping through for loops. I remember the jaw-hitting-floor moment when my C++ book tried to pass off std::vector<int>::iterator it; for (it=arr.begin(); it!=arr.end(); it++) { ... } as an improvement over for (int i=0; i<len; i++) { ... } Not entirely unrelated: I'm currently busy verbosifying a large chunk of C++11 code into C++90 code because Reasons (or so the maintainers assure me).
- ThatOtherPerson 12y agoIt's an improvement in the sense that it's more general; you can loop through any container that implements that protocol, which most (if not all) of the STL containers do. For example, template <class T> void foo(T arr) { for (auto it = arr.begin(); it != arr.end(); ++it) { std::cout << *it << std::endl; } } You could pass a `std::map<int>` to `foo`, or a `std::list<string>`, or a `std::vector<char>`. You could even create your own classes and give them to `foo`, as long as they implement the `begin`/`end` protocol. It's certainly more verbose than necessary, but it can be convenient.
- jjoonathan 12y agoOh yes, and I'm hella thankful for those containers. I just wish "auto" had come along a little sooner :)
- nly 12y agoYou want to use 'T const&' as your argument type, not 'T', otherwise foo() will take a copy of anything you pass.
- zak_mc_kracken 12y agoI've never understood the STL's infatuation with iterators. Why do I even need to know about them when all I want is walk through the collection? Ideally, it should be something like: for (auto it : arr) { // do something with *it }
- jonstewart 12y agoIt basically is this easy these days, thankfully. It is nice to have iterators, though, because it allows you some flexibility for swapping out the underlying data structures on existing algorithmic code. This has proved quite useful when I've written graph code.
- jeorgun 12y agoYou can do that. That's part of C++11 and is supported by basically every major compiler. The advantage of iterators is that they're incredibly flexible. You can use them for sub-ranges, reversed ranges, non-ranges like input and output iterators, etc, etc. This is vastly more powerful than something like, say, Objective C's NSFastEnumeration, which just allows for the trivial case handled by the range-based for-loop.
- mpyne 12y ago> Why do I even need to know about them when all I want is walk through the collection? Because there are algorithms where you may not want to walk through the whole collection. STL wasn't meant to be a container library alone, it also includes many generic algorithms that work using iterators to delimit the range of data to be operated upon.
- azoth_ 12y agoIn modern C++ these loops could alternatively be written as: std::vector<int> myVec; for( auto it = myVec.begin(); it != myVec.end(); ++it ); or if you prefer the external begin/end syntax: for( auto it = std::begin(myVec); it != std::end(myVec); ++it ); or the most succinct (replace && by & if writing): for( auto && item : myVec );
- jjoonathan 12y agoYes, and it's probably good to note that the issue has been fixed so as to not unduly scare away any newcomers to C++. Thanks for doing it for me :) Still, at the time the for(auto& item : vec) syntax was merely a talking point being tossed around C++0x meetings. And to this day the project I'm working on still hasn't officially dropped support for C++90 so I'm stuck with the old syntax anyway :/
- pbsd 12y ago> or the most succinct (replace && by & if writing): That is strictly not necessary. `auto&&` is what is now being called a universal reference: `item` resolves to `const int&` if `myVec` is const, and to `int&` if `myVec` is mutable. `auto&&` does the right thing in the majority of cases. In fact, the following extension [1] has been proposed for C++17 (and already implemented in recent clang builds): for( item : myVec ) { /* do stuff */ } which is meant to be a short-hand for for( auto&& item : myVec ) { /* do stuff */ } [1] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3994.htm http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n399...
- StephanTLavavej 12y agoBoth auto& and auto&& produce const T& for a const vector<T>, and T& for a modifiable vector<T>. The difference between them is subtle: auto&& handles Humanity's Eternal Nemesis, vector<bool>.
- pbsd 12y agoOops, you're right of course; I got reference collapsing rules confused with the regular binding rules. Proxy objects will only bind to auto const& or auto&&, though, since they're generally returned by value. I was surprised to see that this does not come up in std::bitset nor std::valarray, but only std::vector<bool>.
- 72deluxe 12y agoI remember reading Stroustrup's book and not having a clue what an "iterator" was. Even looking in dictionaries didn't help me - I was just after the very definition of the word! Times have changed now of course.
- kazinator 12y agoIndeed! Just to write a class in C++ with a constructor and destructor which are not inlined, you have to repeat the class name about seven times: three times in the class declaration. Then four more times in the definitions of those two functions: class verbose { public: verbose(); ~verbose(); }; verbose::verbose() { } verbose::~verbose() { }