- Some C++14 code - 25 Updates
boltar@cylonHQ.com: Jul 17 08:59AM On Mon, 16 Jul 2018 21:46:05 +0100 >} >Now swap block 1 and block 2 around. Don't forget to edit the free >statements. Sure its extra work, but not that much extra. Besides, if you're really bothered about calling free then just use alloca() and allocate on the stack. No free() required though there may be limits on how much memory the OS or CPU will allow. >The only way I've seen that maintains your sanity is the Linux kernel >way - use goto as an exception. Nothing wrote with that, I use it myself when writing C code. >bool dosomething >{ > unique_ptr<type> a = std::make_unique<type>(); I'd not heard of make_unique. Looked it up, don't see the point. Another C++14 irrelevance. And to be honest, if you're only using those objects in that function, why use a pointer at all? Just use a stack object so no requirement for |
boltar@cylonHQ.com: Jul 17 09:05AM On Tue, 17 Jul 2018 08:13:25 +1200 >>> is a freebie. >> So is using a regular pointer and understanding the code. >So removing something that has no cost is a sound engineering decision? There's no such thing as no cost in creating and destructing objects no matter how slimline they may be and smart pointers are objects. |
Manfred <noname@add.invalid>: Jul 10 05:56PM +0200 On 7/10/2018 4:02 PM, Bart wrote: > The end result was presumably to create an instance of a vector of > size_t initialised to N elements set to some values (I suppose I could > have initialised mine to ten 20s). C++ gives you that, it is called initializer list, and this is what you came across - the defining syntax is a brace-enclosed list of elements, separated by commas. This is different from the 2 argument /constructor/ (no list) which takes 1 value and a number of elements. These are two logically different constructs, which justify the different syntax. > same as you might get in Python or Ruby in Javascript; the details will > vary but you will get the values 10, 20, 30, and 40 printed out in some > form and in that order. Well, C++ does not have a default output for all types - in fact there are 2 kind of outputs: the one inherited from C (stdio) and the standard C++ library, which basically offers output operators for fundamental types (ints, floats, strings) and little (or nothing?) more, it's that simple! Yes, this requires that you write output operators for more complex types (or use a library), but a) in any serious project you /want/ to do just that, so that /you/ control the output format, and b) you don't have to learn what is the default output for those types (C++ is big enough without adding this too, I believe) In fact the examples of Python, Ruby, Javascript are IMHO only good for contexts where the actual output format is not relevant, and this is IMHO only acceptable for e.g. in-house tools. Moreover, these languages require that you learn what is the default format, and how to override it, which I find annoying whenever I need to control my own output. > Or superimpose a user type on it that requires a certain output style > that will use a dedicated stringify routine. But for quickly displaying > the value(s) of a variable, it doesn't matter. In C++ you would do neither, you would define a custom insertion operator (operator <<) that does the job without the need to modify the type system. > (How would a debugger for C++ display such a vector?) (both VS and gdb display it their own way) >>> C++ seem to promise this sort of simplicity in user code (even in a >>> static language rather than my dynamic examples), but I'm not seeing it. >>> The user code syntax seems rather fragile. I believe it can be agreed that simplicity is not a promise of C++, in fact it seems that nowadays Bjarne is concerned that the language is becoming (has already?) too complex. > I'm saying it is fragile. > What are we declaring here? Some sort of flexible, ie. expandable array > of a specific type? Recalling: std::vector<std::size_t> v(10, 20); This declares an object v of type "vector of size_t's" which is a template instantiation of a class template defined in the standard library (which is the same as a user-defined template as far as the language is concerned). I see nothing fragile in it, and it is clearly different from a raw array (which would be: size_t v[length]; ) You may say it is complex or verbose, but I wouldn't define it fragile. You can express that in C with a tweak in the syntax: > with existing arrays) than the C++ where such things have to be > implemented using its language building features. And the syntax for > invoking those has limitations. The way I see it, having flex arrays look like ordinary arrays, but behave differently, would be more fragile than std::vector, and if they were implemented in the language itself instead of a library, they would make the whole language more fragile (i.e. rigid and hard to maintain) |
Rosario19 <Ros@invalid.invalid>: Jul 10 06:00PM +0200 On Mon, 9 Jul 2018 10:23:25 +0200, "Alf P. Steinbach" wrote: >>> struct Sub >>> : Text_item >>> , Itemlist here ther is for me the 1 problem class sub:Tex_item could mean that sub is a 'subset' of class Tex_item (this possible is ok) what does it mean "sub:Tex_item,Itemlist" (the ",Itemlist")? >>> { >>> template< class Item > >>> auto operator<<( Item item ) && i never used auto, but here the problem is for me conceptual: what does it mean "&&"? it appear it means "reference reference" i never tought on that nor used than i miss 100% the meaning of: "auto operator<<( Item item ) && -> Sub&&" >>> -> Sub&& >>> { >>> return static_cast<Sub&&>( i used only C cast () >>> move( *this ).Itemlist::operator<<( item ) this would mean that move has as argument *this, its result is one type has one .Itemlist::operator<<() apply to item... |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jul 10 05:44PM +0200 On 10.07.2018 17:22, red floyd wrote: > I'm assuming the explicit refernce to this is due to some template > weirdness. Otherwise the question becomes, why explicitly specify > "this"? This is a should-have-been-simple-really forwarding to the base class `operator<<`, which is rvalue-qualified. The rvalue qualification means that it must be called on an rvalue expression. I would be happy to learn of some better way than the `move(*this)`. It was the first I could think of, but it is very very ugly to my eyes... So, suggestions/ideas/knowledge very welcome. It's rvalue-qualified so the machinery can be used to construct a menu in a single expression, like this (it's my actual code at the moment): $with( gui_ext::Auto_parent{ *this } ) { using namespace gui_ext::menu_data; const auto& menubar = *new gui_ext::Menu_bar{ Itemlist{} << (Sub{ "App" } << Text_item{ 0, "Blah" } << Text_item{ 0, "Blah blah" } << Separator{} << Text_item{ Cmd::app_exit, "Exit" }) << (Sub{ "Help" } << Text_item{ 0, "Help" } << Separator{} << Text_item{ Cmd::help_about, "About" }), [this]( const int id ) { on_menuitem_picked( id ); } }; ... In between the resulting FLTK menu bar and the pure data Itemlist's << machinery, is a generator class Menu_bar that translates the hierarchy of menu items to FLTK menu text paths, for FLTK menu creation. Yes, it's incredible, but one uses the actual country-specific menu text, forming a path with "/" as separator, to specify an item's hierarchical position. It's so insane that I could not believe it, I wasted a day searching for the more normal functionality that I felt had to be there. Another thing about FLTK, it has an implicit-parent window scheme where any new widget is automatically put, hence no explicit parent specs above. The translation code, mapping the hierarchy of menu data items to FLTK widget, is in the constructor of Menu_bar. It's currently some 70+ lines, far more than I consider reasonable for a function body. But I see no good simple ways to refactor it. I can post it here if someone's willing to take a look and say, you idiot Alf, here's how to do it. E.g. recursive instead of my iterative code, or something? Cheers!, - Alf |
Juha Nieminen <nospam@thanks.invalid>: Jul 10 11:12AM > How exactly does any of this syntatic masturbation solve any problems? Because > lets remember, a programming language is just a tool, not an end in itself. Indeed. Syntactic tools should be used when they make sense, and make the code clearer, easier to use, safer, more understandable, or all of the above. Using them just for the sake of it, especially if it makes the code harder to understand, and especially if there are clearer alternatives, makes no sense. |
boltar@cylonHQ.com: Jul 10 09:55AM On Mon, 9 Jul 2018 17:56:11 +0200 > return static_cast<Sub&&>( > move( *this ).Itemlist::operator<<( item ) > ); And some greybeards wonder why the kids are avoiding C++. God almighty, its virtually unparsable , and thats just 1 line. If I saw a whole program full of this crap I'd just dump the whole thing and re-write it. How exactly does any of this syntatic masturbation solve any problems? Because lets remember, a programming language is just a tool, not an end in itself. >^ This rather ungrokable mess just invokes the base class "operator<<", Well you wrote it. |
boltar@cylonHQ.com: Jul 10 01:01PM On Tue, 10 Jul 2018 14:37:07 +0200 >There are some levels of understanding involved. Naturally you're conversant with all these levels arn't you. >on the basis of feeling uneasy with new language features, and, it seems >to me, on the basis of needing much time to understand unfamiliar >combinations of simple features, that involve 3 or more relationships. If you want to use a car analogy - you're the sort of designer who doesn't actually drive but thought it would be a great idea to have everything controlled by a touchscreen. After all, touchscreen interfaces are common now , everyone uses them and it requires less components. Unfortunately you completely forgot that when driving one can't look at a touchscreen and with zero haptic feedback they're next to useless in that situation so even changing a radio channel or setting the air con becomes impossible unless topped. Technology for its own sake. Similarly with your code - you write code to impress and use as much cutting edge syntax as you can because its there, not because its appropriate or would be maintainable in the wild. Syntax for its own sake. |
Bart <bc@freeuk.com>: Jul 10 03:02PM +0100 On 10/07/2018 13:58, Juha Nieminen wrote: >> std::vector<int> v = {10,20,30,40}; > It's not doing the same thing at all. Nor is it demonstrating the point > of my post. The end result was presumably to create an instance of a vector of size_t initialised to N elements set to some values (I suppose I could have initialised mine to ten 20s). >> v := (10,20,30,40) >> println v # output: (10,20,30,40) > Why should it write "(10,20,30,40)"? Because that's the default output for that type in this language? The same as you might get in Python or Ruby in Javascript; the details will vary but you will get the values 10, 20, 30, and 40 printed out in some form and in that order. > Why not "10, 20, 30, 40"? Or "[10, 20, 30, 40]"? Or "[10,20,30,40]"? > Or each number in its own line? Or the about one million other possible > variations? Why is that the "correct" one? You can write a printlist() routine for a generic list to get it displayed as you want. Or superimpose a user type on it that requires a certain output style that will use a dedicated stringify routine. But for quickly displaying the value(s) of a variable, it doesn't matter. (How would a debugger for C++ display such a vector?) > Fragile... What exactly is it that you want? For the compiler to guess > using AI what you *really* wanted to say, even though it's not syntactically > correct? I'm saying it is fragile. What are we declaring here? Some sort of flexible, ie. expandable array of a specific type? You can express that in C with a tweak in the syntax: int v[flex] = {10,20,30,40}; Of course, 'flex' arrays would need to be implemented. The point is that such syntax for them is more robust and also tidier (and more consistent with existing arrays) than the C++ where such things have to be implemented using its language building features. And the syntax for invoking those has limitations. -- bart |
Bart <bc@freeuk.com>: Jul 10 01:24PM +0100 On 10/07/2018 12:20, Juha Nieminen wrote: > A naive implementation of std::vector would fail to compile that. Why? > Because it will try to call the version of the constructor taking two > iterators (and then fail to compile because those are not iterators). I couldn't get this to compile at all. (Note I don't normally write C++ code and I used an online 'rextester.com' C++ compiler. I'm writing this as an observer.) First, it needed '#include <vector>' (Why? isn't it part of std?). Then it couldn't find a match for 'unsigned long long int' (size_t). Using just <int> was OK, but then it didn't understand v(10) or v(10,20). I finally got this compiled: std::vector<int> v = {10,20,30,40}; but if I then added: std::cout << v << std::endl; I got several hundred lines of error messages. So although your point is about why internal libraries might be complicated, mine is that even what should be straightforward user code is not that friendly! I'd write this stuff in dynamic code like this: v := (10,20,30,40) println v # output: (10,20,30,40) v is a writeable, flexible-length list with variant elements. A flexible, packed array of a fixed element type closest to the C++ is doable although it is a little outside the language: v := new(array,word64,10,20) # word32 == size_t println v, v.bounds This now matches your example and the output now is (20,20,20,20,20,20,20,20,20,20) 1..10 What I'm saying is that the hugely complex language building features of C++ seem to promise this sort of simplicity in user code (even in a static language rather than my dynamic examples), but I'm not seeing it. The user code syntax seems rather fragile. -- bart |
bitrex <user@example.net>: Jul 09 09:34AM -0400 On 07/09/2018 04:23 AM, Alf P. Steinbach wrote: > rules of rvalue-ref-as-argument. > Cheers!, > - Alf If one is actually utilizing the new features the modern C++ standards have available code is often not going to look a lot like what "very experienced" C++ programmers remember it looking like in 1997 that's just the way it is. |
Juha Nieminen <nospam@thanks.invalid>: Jul 10 06:29AM > have available code is often not going to look a lot like what "very > experienced" C++ programmers remember it looking like in 1997 that's > just the way it is. What makes you think that my comment had anything to do with C++98 vs C++11? Code can be made more obfuscated in several ways, such as using unusual and confusing indentation and line breaks, among a myriad other techniques. Also, using alternative syntax just for the sake of it, even though it's the less commonly used one, can make code needlessly hard to read. As an example, one of the major reasons why the trailing return type syntax for function declarations was introduced is that it makes it simpler to declare the return type when it depends on the names of the function paramers. The classical example is: template <class T, class U> auto add(T t, U u) -> decltype(t + u); Achieving this was possible in C++98, but it was much more complicated. This syntax introduced in C++11 makes it much simpler. However, once you start writing things like: auto main() -> int it just seems needlessly complicated for no good reason. Everybody and their grandmother understands "int main()", and using the trailing type syntax serves mostly the use of making the code harder to read. (It also kind of reminds me, in a way, of how in K&R C the types of the function parameter were not specified inside the parentheses in front of the parameter names, but separately after the parentheses. So, in a weird sense, it feels a bit like going back in time to the 80's. And not necessarily in a good way.) I also find it odd how he's fond of the more verbose trailing type syntax, while at the same time eschewing specifying whether he's inheriting the struct publicly or privately from the base classes. Verbosity isn't itself a bad thing, especially when it makes the code easier to read and understand. But using additional verbosity in situations that makes the code harder to understand, and at the same time avoiding verbosity in situations when doing so also makes the code harder to understand, is a bit baffling. It almost feels deliberate. If you are inheriting your class or struct from something, always specify the type of inneritance. Saying "struct A: B, C" is just confusing. Is it public inheritance, or is it private inheritance? Just put the keywords there to clarify. |
Vir Campestris <vir.campestris@invalid.invalid>: Jul 09 09:52PM +0100 On 09/07/2018 15:37, Bart wrote: > compared to the C equivalent. Or maybe the C++ experts here just like to > show off their skills at writing incomprehensible code, which is not > typical of normal programs. The last heavyweight bit of C I wrote was a hash set. I had to use C as it was running bare metal, so I couldn't use anything nice like new. I can assure you that the several pages of code were a lot harder to read than the C++ equivalent, most of which would have just pulled in STL. Andy |
boltar@cylonHQ.com: Jul 10 09:48AM On Mon, 9 Jul 2018 21:52:35 +0100 >it was running bare metal, so I couldn't use anything nice like new. >I can assure you that the several pages of code were a lot harder to >read than the C++ equivalent, most of which would have just pulled in STL. You ever read the STL source code? Its enough to make anyone weep. There's no reason a similar library (albeit without the templating) couldn't be written in C and then the application code using it would look a lot tidier. |
red floyd <no.spam@its.invalid>: Jul 10 08:22AM -0700 On 07/07/2018 07:27 PM, Alf P. Steinbach wrote: > ); > } > ... OK, I'll ask the obvious. Why (*this).Itemlist instead of this->Itemlist I'm assuming the explicit refernce to this is due to some template weirdness. Otherwise the question becomes, why explicitly specify "this"? |
bitrex <user@example.net>: Jul 09 11:27AM -0400 On 07/09/2018 10:37 AM, Bart wrote: > in the clc group, C++ is frequently sold as a language which is so much > easier and better than C because it has so many built-in solutions to > things that have to be re-implemented in C. Sounds like they're "selling" C++ wrong, whomever is selling it that way. The _runtime_ component of C++, the actual stuff that gets parsed directly into object code, is really nothing much more than a mild superset of C, a simplistic 1970s-style statically-typed language. That's component #1 of C++. Component #2 is a powerful modern compile-time meta-programming language that's used to manipulate the component #1s into zero-overhead abstractions. > compared to the C equivalent. Or maybe the C++ experts here just like to > show off their skills at writing incomprehensible code, which is not > typical of normal programs. They're exploiting Component #2 for what it's good for. If you're not doing that you're...basically just programming in a kind of dumpy obtuse variant of C I won't deny it, there's really not much advantage to using C++ at that point over many other modern compiled languages like Go, Rust, and so forth. Standing by itself Component #1 ain't shit, or at least no more or less the shit than C. |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jul 10 03:37PM +0200 On 10.07.2018 14:58, Juha Nieminen wrote: > Only the first one is relevant and will tell you the problem. > What exactly do you think should happen if you try to output a > vector to a stream? Something reasonable. It doesn't matter exactly what the output is, except for the distinction between display for humans, versus round-trip conversion support where the text representation can be parsed and yield the original data. I've briefly encountered a number of libraries that produce reasonable text output of any standard library container. So it's possible. It's just not standardized and readily available, which would have been nice. > Fragile... What exactly is it that you want? For the compiler to guess > using AI what you *really* wanted to say, even though it's not syntactically > correct? IMO most of the problems with silly error avalanches in C++ stem from using too low level language features to directly implement higher level stuff, because the language lacks the middle level of abstraction. For example, because of the lack of abstraction an error message will typically show the complete template instantiation for something, instead of just a simple recognizable name like `std::string`. With C++ templates we're essentially using `goto` directly instead of structured flow control like `for` loops. So, in that analogy, the errors don't relate to loop variant and invariants, or something like that, but instead to invalid position for label, computed goto with possibly invalid resulting jump address, ... blah blah details details, of no interest to one whose goal is to loop over items of a collection. Cheers!, - Alf |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jul 09 05:56PM +0200 On 09.07.2018 16:37, Bart wrote: > complicated and harder to understand than what is already in the language. > In contrast, I consider a useful new feature ought to make things > simpler and easier. I agree with that. > I actually haven't got a clue what the code at the top is doing. Yes, it's pretty intricate code, using C++14 language features, which look odd and have strange rules. Here's a breakdown: struct Sub : Text_item , Itemlist ^ Declares a class called Sub, that inherits from -- Is A -- class Text_item and from class Itemlist. What Text_item and Itemlist are doesn't matter. template< class Item > ^ Introduces a template of something, that can be used with a type that can be wildly different types in different usage contexts. The concrete type used in any given context is called Item in this definition. auto operator<<( Item item ) && -> Sub&& ^ The "auto operator<<(" starts a declaration of a member function called "operator<<". "auto" says that the return type is specified after the function head, either implicitly via a "return" statement (a C++14 deduced return type) or explicitly via a "->" return type specification (C++11 trailing return type syntax). The function name "operator<<" means that this function can be called via operator notation, e.g. the invocation "o << an_item", which is how e.g. iostreams work. "( Item item )" is the function's formal argument list, just like in C. Here an Item is passed by value. "&&" means that this function can only be called via an rvalue expression, essentially calling it on a temporary. More precisely it can also be called on the result of a function that returns an rvalue reference, because that acts as if it were a temporary. So, the "&&" is an rvalue qualification of the member function. There are also lvalue qualification "&", and const lvalue qualification "const &". -> Sub&& Specifies that the return type is rvalue-reference-to-Sub, i.e. (as-if) a reference to a temporary Sub object. return static_cast<Sub&&>( move( *this ).Itemlist::operator<<( item ) ); ^ This rather ungrokable mess just invokes the base class "operator<<", and, via the "static_cast", downcasts the result to this class. It should IMHO have been trivial to do that, it's just a /forwarding/ of the call to a base class method, but it isn't trivial. Instead of downcasting the base class' result it could have been separated into two statements like this: move( *this ).Itemlist::operator<<( item ); return move( *this ); That's perhaps better for discussion. The "move( *this )" doesn't actually move anything. It uses "std::move" as a /cast/ to create an rvalue reference to the current object, needed in the first line because the base class "operator<<" can only be called via an rvalue expression. The ".Itemlist::operator<<" then refers to the "operator" defined in the base class "Itemlist". And the "( item )" expresses the call with "item" as argument, just like in C. "move( *this )" is also needed in the return statement, since this "operator<<", like the one in the base class, returns an rvalue reference. In the originally posted code there is no "move( *this )" for the result because that's expressed by a "static_cast". > in the clc group, C++ is frequently sold as a language which is so much > easier and better than C because it has so many built-in solutions to > things that have to be re-implemented in C. The rvalue stuff in this code addresses problems that stem from what I'd call a cognitive dissonance in the C++ type system. The original C lvalue versus rvalue expression classification was presumably useful to help the compiler put temporary results in registers, where on most machines one couldn't take the address. Also one couldn't assign to rvalues. The put-in-registers made for execution efficiency, and the can't-assign-to made for programmer efficiency; it all made sense. In C++ there are rvalue expressions that denote objects of arbitrary size and complexity, that necessarily do live in main memory, and that generally /can/ be assigned to. That doesn't make so much sense. So the code to handle this, with the old distinction still ruling, gets ungood. > compared to the C equivalent. Or maybe the C++ experts here just like to > show off their skills at writing incomprehensible code, which is not > typical of normal programs. There must be many books and articles about C++ that cater to C programmers. If nothing else, I enjoyed learning C++ from the original "The C++ Programming Language" by Bjarne Stroustrup. I think that was published in 1985. That first edition was of the same general form as the earlier "The C Programming Language" by Kernighan & Ritchie. The first edition of TCPPL was about the pre-standard simpler language that's still to be found within all the complexity of modern C++. I think that book was before exceptions and templates. Exceptions were introduced around 1989, IIRC, templates later. Cheers!, - Alf |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jul 10 02:37PM +0200 On 10.07.2018 13:12, Juha Nieminen wrote: > Using them just for the sake of it, especially if it makes the code harder > to understand, and especially if there are clearer alternatives, makes no > sense. There are some levels of understanding involved. I've always disagreed strongly with those who maintain that one who doesn't have 20 years experience in designing cars, can't evaluate a car design with square wheels. Because that problem is obvious. The argument that one is disqualified is a purely associative one, idiotic IMHO, although it must be said that that argument often /works/, when it appeals to authority in a direction that the herd has experience with. But that's not what you're doing here. You're not evaluating on the basis of seeing square wheels or something like that. You're evaluating on the basis of feeling uneasy with new language features, and, it seems to me, on the basis of needing much time to understand unfamiliar combinations of simple features, that involve 3 or more relationships. That's like the close-voters on Stack Overflow who decide that someone's question must be off-topic or nonsense because they don't understand it, sometimes even in the face of very clear answers to that question. That is, they're using their inflated opinions of their own competence, to infer from their own lack of understanding that the question must be nonsense. Or else they would have understood it, surely. Their reaction is not to ask about anything, for what could there be to ask about?, and besides that would be outside their comfort zone; they instead simply vote to close, to get this to them affronting nonsense out of the way. Cheers!, - Alf (social focus mode) |
Juha Nieminen <nospam@thanks.invalid>: Jul 09 07:57AM > move( *this ).Itemlist::operator<<( item ) > ); > } You have an uncanny ability of writing C++ in a form that causes even a very experienced C++ programmer to have to spend an unreasonable amount of time staring at the code trying to figure out what it means. |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jul 09 10:23AM +0200 On 09.07.2018 09:57, Juha Nieminen wrote: > You have an uncanny ability of writing C++ in a form that causes even a > very experienced C++ programmer to have to spend an unreasonable amount > of time staring at the code trying to figure out what it means. That's interesting, when ignoring the personal jab. On what line does it get problematic for you? As reported, for me, very late at night, it was the `static_cast`, somehow then conflating the rules for rvalue-ref-as-return with the rules of rvalue-ref-as-argument. Cheers!, - Alf |
Juha Nieminen <nospam@thanks.invalid>: Jul 10 11:20AM > You ever read the STL source code? Its enough to make anyone weep. There's > no reason a similar library (albeit without the templating) couldn't be > written in C and then the application code using it would look a lot tidier. The reason why templated code in the standard library tends to be complex is for two main reasons: Firstly, it needs to make all kinds of compile-time sanity checks that are a bit complicated to perform (but which the regular programmer doesn't need to worry about). These have to be done to ensure that the class or function does what it should, and is as hard to use incorrectly as possible. For example, suppose you have something like this: std::vector<std::size_t> v; v(10, 20); A naive implementation of std::vector would fail to compile that. Why? Because it will try to call the version of the constructor taking two iterators (and then fail to compile because those are not iterators). However, the standard std::vector will compile, and do the right thing (ie. create a vector of 10 elements, each having the value 20.) How? Well, that's the complicated part, which makes the source code a bit complex. And if you *do* give it two iterators of the same type, it will still compile and do the right thing. Secondly, the standard library headers tend to look very messy because all internal names tend to be prefixed with two underscores. This is done out of necessity, so that user-defined precompiler macros won't mess things up and cause weird compiler errors (or in the worst case scenario compilable code that's broken). (Remember that the standard forbids the user from using names with two leading underscores. If you use them, all bets are off. As long as you don't use them, you ought to be safe.) |
Juha Nieminen <nospam@thanks.invalid>: Jul 10 12:58PM >> std::vector<std::size_t> v; >> v(10, 20); > I couldn't get this to compile at all. I made a mistake in that code. What I meant to say was: std::vector<std::size_t> v(10, 20); > std::vector<int> v = {10,20,30,40}; It's not doing the same thing at all. Nor is it demonstrating the point of my post. > but if I then added: > std::cout << v << std::endl; > I got several hundred lines of error messages. Only the first one is relevant and will tell you the problem. What exactly do you think should happen if you try to output a vector to a stream? > I'd write this stuff in dynamic code like this: > v := (10,20,30,40) > println v # output: (10,20,30,40) Why should it write "(10,20,30,40)"? Why not "10, 20, 30, 40"? Or "[10, 20, 30, 40]"? Or "[10,20,30,40]"? Or each number in its own line? Or the about one million other possible variations? Why is that the "correct" one? > C++ seem to promise this sort of simplicity in user code (even in a > static language rather than my dynamic examples), but I'm not seeing it. > The user code syntax seems rather fragile. Fragile... What exactly is it that you want? For the compiler to guess using AI what you *really* wanted to say, even though it's not syntactically correct? |
Ian Collins <ian-news@hotmail.com>: Jul 10 03:25PM +1200 On 10/07/18 02:37, Bart wrote: > complicated and harder to understand than what is already in the language. > In contrast, I consider a useful new feature ought to make things > simpler and easier. Which is what most of C++14 did... > in the clc group, C++ is frequently sold as a language which is so much > easier and better than C because it has so many built-in solutions to > things that have to be re-implemented in C. The code is hard to follow, partly due to the unusual (to my eyes) layout compounded by the gratuitous use of suffix return.. I'm sure if I submitted it to a code review I'd get more than a few WTF? responses! Most builtin or library features such as containers and algorithms do make things easier and better than C. > compared to the C equivalent. Or maybe the C++ experts here just like to > show off their skills at writing incomprehensible code, which is not > typical of normal programs. Most C++ code I see is pretty mundane. The "clever" stuff is usually confined to libraries. -- Ian. |
Bart <bc@freeuk.com>: Jul 09 03:37PM +0100 On 09/07/2018 14:34, bitrex wrote: > have available code is often not going to look a lot like what "very > experienced" C++ programmers remember it looking like in 1997 that's > just the way it is. It sounds like C++ programmers expect new features to be more complicated and harder to understand than what is already in the language. In contrast, I consider a useful new feature ought to make things simpler and easier. I actually haven't got a clue what the code at the top is doing. However in the clc group, C++ is frequently sold as a language which is so much easier and better than C because it has so many built-in solutions to things that have to be re-implemented in C. It's odd then that I rarely come across a C++ example which I can follow compared to the C equivalent. Or maybe the C++ experts here just like to show off their skills at writing incomprehensible code, which is not typical of normal programs. -- bart |
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page. To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com. |
No comments:
Post a Comment