Tuesday, July 17, 2018

Digest for comp.lang.c++@googlegroups.com - 25 updates in 1 topic

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: