The worst things about C++

  • Thread starter Steven T. Hatton
  • Start date
S

Steven T. Hatton

No, this is not a troll, and I am not promoting Java, C-flat, D, APL, Bash,
Mathematica, SML, or LISP. A college teacher recently posted to this
newsgroup regarding her observation that there has been a significant
decline in the number of students opting to take courses in C++. I just
want to let people know what I believe are the biggest obstacles to C++
language acquisition, and what aspects of the language make it less
appealing than it could be.

None of these are integral to the core language. The typical selling points
for Java and Microsoft's Java-like pseudo-C++ are "garbage collection"
and "no unsafe access (pointers)". I am convinced that neither of those
issues are weaknesses of C++. Both of these are actually strengths of C++
in comparison to the competing languages. RAII forces the programmer to
know what he or she is really doing with resources, and leads to cleaner,
more coherent code. Certainly pointers can result in problems if not
handled correctly. OTOH, the direct access to addressable memory enables
many optimizations and capabilities which the other languages have to
provide by modifying the language implementation (which is more than likely
written in C++). There are plenty of programming practices which protect
against traditional buffer overrun problems, etc.

What I found most problematic when learning C++ were, roughly in order of
significance:

Cpp. Almost everything about it from its ugly syntax to its brutish
disregard for program structure have been problems for me. Reading code
with Cpp conditionals is often confusing because one must know and keep in
mind what conditions hold at compile time for the particular build we are
working with. It cuts up syntax without regard for program correctness.
It can lead to unexpected behavior which is not obvious because its
consequences are manifested between the time the code is seen by the
programmer and the time it is seen by the compiler. It can be used to
arbitrarily rearrange and redefine program components. Even the #include
mechanism can cause significant problems. For example when header guard
name collisions happen they lead to hard to understand errors for which the
compiler typically provides worse than useless diagnostics. Name
collisions among macros are also significantly problematic. And these are
just a few of the objections I have to Cpp usage.

The related issues of ODR subtleties, the exact nature of linkage and
translation units has been another source of significant confusion for me.
This also ties into the use of the #include mechanism of Cpp. But it goes
beyond that. The concept of a translation unit is not symbolically
represented in the language, but it plays a significant role in the
structure of a program. The meaning and implication of static and extern
have always been nebulous to me. Only recently have I really come to
understand them.

Though it is, to a large extent, outside the scope addressed by the
programming language itself, the issue of library linkage has also been a
significant source of trouble for me.

The only aspect of the core language I really find problematic, and this is
far less significant than any of the above, is the syntax related to
pointers to functions, and the syntax related to passing references to
arrays. The latter is something that Stroustrup seems to have omitted
completely from TC++PL(SE).
 
I

Ian Collins

Steven said:
What I found most problematic when learning C++ were, roughly in order of
significance:

Cpp. Almost everything about it from its ugly syntax to its brutish
disregard for program structure have been problems for me.

The cost of retaining backwards compatibility with 30+ year old tools
and techniques. New languages have the luxury of defining their own
infrastructure.
Reading code
with Cpp conditionals is often confusing because one must know and keep in
mind what conditions hold at compile time for the particular build we are
working with. It cuts up syntax without regard for program correctness.
It can lead to unexpected behavior which is not obvious because its
consequences are manifested between the time the code is seen by the
programmer and the time it is seen by the compiler.

These problems can largely be removed by the use of conditional builds,
rather than conditional compiles. A conditional build splits platform
specific code into its own compilation unit.
It can be used to
arbitrarily rearrange and redefine program components. Even the #include
mechanism can cause significant problems. For example when header guard
name collisions happen they lead to hard to understand errors for which the
compiler typically provides worse than useless diagnostics. Name
collisions among macros are also significantly problematic. And these are
just a few of the objections I have to Cpp usage.
I can't argue with that. Although in my experience the problem is rare
and once bitten one learns the symptoms.
The related issues of ODR subtleties, the exact nature of linkage and
translation units has been another source of significant confusion for me.
This also ties into the use of the #include mechanism of Cpp. But it goes
beyond that. The concept of a translation unit is not symbolically
represented in the language, but it plays a significant role in the
structure of a program.

Again, the cost of retaining backwards compatibility with 30+ year old
tools and techniques.
The only aspect of the core language I really find problematic, and this is
far less significant than any of the above, is the syntax related to
pointers to functions, and the syntax related to passing references to
arrays.

The declaration and use of pointers to members is without doubt an
abomination.
 
G

Gianni Mariani

Ian said:
Steven T. Hatton wrote: ....
The declaration and use of pointers to members is without doubt an
abomination.

What is your proposed alternative ?
 
S

Signal9

Ian said:
The cost of retaining backwards compatibility with 30+ year old tools
and techniques. New languages have the luxury of defining their own
infrastructure.


These problems can largely be removed by the use of conditional builds,
rather than conditional compiles. A conditional build splits platform
specific code into its own compilation unit.

I can't argue with that. Although in my experience the problem is rare
and once bitten one learns the symptoms.


Again, the cost of retaining backwards compatibility with 30+ year old
tools and techniques.

The declaration and use of pointers to members is without doubt an
abomination.

If you dont like it you can start from scratch and build it from top to
bottom in C++... go try that in java (or wait you cant).

I like C++ and Java but they have their own purposes and uses. Also if
you are new to the technology field and want to become a developer, you
need to learn many techniques and languages. Do not stop and sit with
one language and framework/platform, learn everything you can.

Right now the three strongest skills that company's are looking for in
a dev is: C++ (still number one), Java and C#.
 
I

Ian Collins

Signal9 wrote:

[unreferenced posting snipped]
If you dont like it you can start from scratch and build it from top to
bottom in C++... go try that in java (or wait you cant).

I like C++ and Java but they have their own purposes and uses. Also if
you are new to the technology field and want to become a developer, you
need to learn many techniques and languages. Do not stop and sit with
one language and framework/platform, learn everything you can.

Right now the three strongest skills that company's are looking for in
a dev is: C++ (still number one), Java and C#.
Please trim text you are not replying to.
 
S

Steve Pope

Steven T. Hatton said:
What I found most problematic when learning C++ were, roughly in order of
significance:
Cpp. Almost everything about it from its ugly syntax to its brutish
disregard for program structure have been problems for me. Reading code
with Cpp conditionals is often confusing because one must know and keep in
mind what conditions hold at compile time for the particular build we are
working with. It cuts up syntax without regard for program correctness.
It can lead to unexpected behavior which is not obvious because its
consequences are manifested between the time the code is seen by the
programmer and the time it is seen by the compiler. It can be used to
arbitrarily rearrange and redefine program components. Even the #include
mechanism can cause significant problems. For example when header guard
name collisions happen they lead to hard to understand errors for which the
compiler typically provides worse than useless diagnostics. Name
collisions among macros are also significantly problematic. And these are
just a few of the objections I have to Cpp usage.
The related issues of ODR subtleties, the exact nature of linkage and
translation units has been another source of significant confusion for me.
This also ties into the use of the #include mechanism of Cpp. But it goes
beyond that. The concept of a translation unit is not symbolically
represented in the language, but it plays a significant role in the
structure of a program. The meaning and implication of static and extern
have always been nebulous to me. Only recently have I really come to
understand them.
Though it is, to a large extent, outside the scope addressed by the
programming language itself, the issue of library linkage has also been a
significant source of trouble for me.

Seems to me that all the above issues -- Cpp, linkage, translation
units, extern, static -- are inherited from C. This has the dual
problem of (1) some aspects of these features being out of date, and
therefore not part of "good" C++, and (2) long-time C programmers
know intuitively how these things work, and so don't think much
about what problems they might cause for other programmers.

This might again be an argument for learning C first.

BTW, I like C/C++'s concept of separate translation and linkage
between translation units. It's very strong in practice.

Steve
 
S

Salt_Peter

Steven said:
No, this is not a troll, and I am not promoting Java, C-flat, D, APL, Bash,
Mathematica, SML, or LISP. A college teacher recently posted to this
newsgroup regarding her observation that there has been a significant
decline in the number of students opting to take courses in C++.

If i recall, that teacher noted how a local company (ie: Electronic
Arts) has serious problems hiring C++ programmers (thats all they do).
Fact is: its industry, not student's preferences, that dictates what is
in fact "declining".
What I found most problematic when learning C++ were, roughly in order of
significance:

Cpp. Almost everything about it from its ugly syntax to its brutish
disregard for program structure have been problems for me. Reading code
with Cpp conditionals is often confusing because one must know and keep in
mind what conditions hold at compile time for the particular build we are
working with. It cuts up syntax without regard for program correctness.
It can lead to unexpected behavior which is not obvious because its
consequences are manifested between the time the code is seen by the
programmer and the time it is seen by the compiler.

Syntax problems are often coder generated.
Macros should not be used in Cpp.
I find Cpp compiler diagnostics to be considerably better than most
other languages - where diagnostics are non-existant and debugging is
near impossible.
The related issues of ODR subtleties, the exact nature of linkage and
translation units has been another source of significant confusion for me.
This also ties into the use of the #include mechanism of Cpp. But it goes
beyond that. The concept of a translation unit is not symbolically
represented in the language, but it plays a significant role in the
structure of a program. The meaning and implication of static and extern
have always been nebulous to me. Only recently have I really come to
understand them.

Statics should be replaced by namespaces and i'll agree as far as
translation units are concerned although thats nothing unmaneageable.
Though it is, to a large extent, outside the scope addressed by the
programming language itself, the issue of library linkage has also been a
significant source of trouble for me.

The only aspect of the core language I really find problematic, and this is
far less significant than any of the above, is the syntax related to
pointers to functions, and the syntax related to passing references to
arrays. The latter is something that Stroustrup seems to have omitted
completely from TC++PL(SE).

Take Java, for instance, where a reference is actually a naked pointer.
At least C++ gives you the option of using either ptr or ref.
Arrays and pointers should not be used except as a last resort. Most
qualified Cpp programmers are able to write thousands of lines of code
without ever needing an array and much less a dumb pointer (exception:
smart pointers).
 
E

Evan

Steven said:
No, this is not a troll, and I am not promoting Java, C-flat, D, APL, Bash,
Mathematica, SML, or LISP. A college teacher recently posted to this
newsgroup regarding her observation that there has been a significant
decline in the number of students opting to take courses in C++. I just
want to let people know what I believe are the biggest obstacles to C++
language acquisition, and what aspects of the language make it less
appealing than it could be.

None of these are integral to the core language. The typical selling points
for Java and Microsoft's Java-like pseudo-C++ are "garbage collection"
and "no unsafe access (pointers)". I am convinced that neither of those
issues are weaknesses of C++. Both of these are actually strengths of C++
in comparison to the competing languages. RAII forces the programmer to
know what he or she is really doing with resources, and leads to cleaner,
more coherent code. Certainly pointers can result in problems if not
handled correctly. OTOH, the direct access to addressable memory enables
many optimizations and capabilities which the other languages have to
provide by modifying the language implementation (which is more than likely
written in C++). There are plenty of programming practices which protect
against traditional buffer overrun problems, etc.

But in most other languages it's enforced while in C++ it depends on
those conventions. Where the tradeoff is.. I don't know. There isn't
one in general I think, it depends on the application.

If you have a well diciplined programming team which is working off of
a good code base, C++'s supposed weaknesses aren't. If you're handed a
legacy C app that has elements of C++ grafted on but still has pointers
out the wazoo... then I'll take memory safety please. (Unless there's a
good reason for performance needs.)

What I found most problematic when learning C++ were, roughly in order of
significance:

Cpp. Almost everything about it from its ugly syntax to its brutish
disregard for program structure have been problems for me. Reading code
with Cpp conditionals is often confusing because one must know and keep in
mind what conditions hold at compile time for the particular build we are
working with. It cuts up syntax without regard for program correctness.
It can lead to unexpected behavior which is not obvious because its
consequences are manifested between the time the code is seen by the
programmer and the time it is seen by the compiler. It can be used to
arbitrarily rearrange and redefine program components. Even the #include
mechanism can cause significant problems. For example when header guard
name collisions happen they lead to hard to understand errors for which the
compiler typically provides worse than useless diagnostics. Name
collisions among macros are also significantly problematic. And these are
just a few of the objections I have to Cpp usage.

As someone who has been bitten by CPP crap a few times (who TF names a
macro "current"? I'm looking at you Linux kernel devs... it took me
like 20 very frustrating minutes to find out why "int current;" gave a
compile error)... I wouldn't give it up.

There have been too many times when I've used it to reduce code
duplication, or (when programming Java) said "man, I wish a had a
preprocessor".

I think there are definite improvements that could be made to the
mechanism though to reduce the "I'm stepping on your toes" effect, but
coming up with sufficently powerful mechanisms that didn't do that
would take some thought.
The only aspect of the core language I really find problematic, and this is
far less significant than any of the above, is the syntax related to
pointers to functions,

I gripe about this a lot. I used to say that it was inconsistent,
because poniters to functions were the only type where declarations
didn't look like <type> <name>, and instead the name is in the middle
of the thing.

Just a few days ago I realized that this isn't really true: arrays also
take the same form. "int c[10];" in some sense would be better
represented, as Java and C# do it, by "int[10] c;" because c isn't an
int, it's an int array. So that really is another example of the name
(c) appearing in the middle of the type (int[10]). So function pointer
syntax isn't as... unique as I was thinking.

Though I still think that it's crap. I semi-joke that Ritchie must have
been high when he came up with that, which makes sense given the time
period.

--

This seems like as good a place as any to air my newly-developed syntax
gripes. I'm working on a C++ front end to do source-to-source
transformation, and the "print out the modified source" is fairly
buggy. It' a pain to fix because of a few things, but one of them is
that there are a bunch of special cases in C++ that you have to deal
with.

(Actually I'd appreciate any explanations if there are any reasons for
these things that I don't know about.)

1. Typename is required before dependent types, but prohibited before
non-dependent types. This means that I can't just uniformly print out
"typename" before printing the name of a type. Instead, I have to
determine whether the type I'm about to output is dependent or not.
(This is made difficult by the fact that I fully qualify names, so
something that wasn't dependent when it was parsed so isn't represented
as a dependent name can become dependent when it's printed.)

2. Elaborated names can't be used when printing explicit calls to
constructors. Again, for uniformity, Elsa always prints elaborated
names. So:
class C {};
C c;
will output with the second line reading "class C c;". But this doesn't
work in the following context:
void foo(C);
void bar() { foo( C() ); }
because the second line prints as
void bar() { foo( class C() ); }
which is not legal. Thus I have to supress printing the keyword when
printing the creation of temoraries like that.

3. Qualifiers that mark class members cannot be printed in definitions
outside of the class:
class C {
virtual void foo();
};
virtual void C::foo() { }
is not legal. (The same applies to static and explicit.)

4. Default arguments cannot be included at the definition of a
function. (This and #3 were mostly coded when I started working on the
project, but each had situations where sometimes specialized versions
of classes or members didn't supress printing the key piece of
information.)

Evan
 
K

Kai-Uwe Bux

Steven said:
No, this is not a troll, and I am not promoting Java, C-flat, D, APL,
Bash,
Mathematica, SML, or LISP. A college teacher recently posted to this
newsgroup regarding her observation that there has been a significant
decline in the number of students opting to take courses in C++. I just
want to let people know what I believe are the biggest obstacles to C++
language acquisition, and what aspects of the language make it less
appealing than it could be.

None of these are integral to the core language. The typical selling
points for Java and Microsoft's Java-like pseudo-C++ are "garbage
collection"
and "no unsafe access (pointers)". I am convinced that neither of those
issues are weaknesses of C++. Both of these are actually strengths of C++
in comparison to the competing languages. RAII forces the programmer to
know what he or she is really doing with resources, and leads to cleaner,
more coherent code. Certainly pointers can result in problems if not
handled correctly. OTOH, the direct access to addressable memory enables
many optimizations and capabilities which the other languages have to
provide by modifying the language implementation (which is more than
likely
written in C++). There are plenty of programming practices which protect
against traditional buffer overrun problems, etc.

What I found most problematic when learning C++ were, roughly in order of
significance:
[snip]

Ok, and here is what I dislike most about C++ in no particular order:

a) 8.3.5/5, in particular the rule about initialization of const references
and the fact that one cannot bind temporaries to non-const references.

b) that typeid returns a by and large useless type_info object where it
could return a full-fledged type object that would allow for introspection
and allocation/construction of variables of that type.

c) that I cannot overload the dot operator, e.g., so that I could have smart
references or _1.member_function() in lambda.

d) that C++ doesn't have virtual member templates.

e) that my beloved templates produce error messages that fill multiple
screens.

f) that the standard is worded according to the philosophy "when in doubt,
declare the behavior undefined".

g) that the standard library components have too restrictive requirements,
e.g., list<T> requires the type T to be complete.

h) that there is no integral type or typedef guaranteed to be long enough to
hold a void*, and that there is no useful conversion to integral types for
function and member function pointers.


Here is a shorter list of minor nuisances:

A) that there is no guarantee that one can derive from standard
container/iterator classes.

B) that signed integral types make virtually no useful guarantees, and that
std::limits does not provide enough information to work around that
problem.

C) that there is no arbitrary precision / big integer class and no matrix /
tensor template in the standard.

D) that there is no window / gui support in the standard.


Best

Kai-Uwe Bux
 
D

Duane Hebert

Kai-Uwe Bux said:
Ok, and here is what I dislike most about C++ in no particular order:

a) 8.3.5/5, in particular the rule about initialization of const
references
and the fact that one cannot bind temporaries to non-const references.

b) that typeid returns a by and large useless type_info object where it
could return a full-fledged type object that would allow for introspection
and allocation/construction of variables of that type.

c) that I cannot overload the dot operator, e.g., so that I could have
smart
references or _1.member_function() in lambda.

d) that C++ doesn't have virtual member templates.

e) that my beloved templates produce error messages that fill multiple
screens.

f) that the standard is worded according to the philosophy "when in doubt,
declare the behavior undefined".

g) that the standard library components have too restrictive requirements,
e.g., list<T> requires the type T to be complete.

h) that there is no integral type or typedef guaranteed to be long enough
to
hold a void*, and that there is no useful conversion to integral types for
function and member function pointers.


Here is a shorter list of minor nuisances:

A) that there is no guarantee that one can derive from standard
container/iterator classes.

B) that signed integral types make virtually no useful guarantees, and
that
std::limits does not provide enough information to work around that
problem.

C) that there is no arbitrary precision / big integer class and no matrix
/
tensor template in the standard.

D) that there is no window / gui support in the standard.
For me (in addition to most of your points):

A) std::limits<Any integral type>::min() returns the
minimum value the type can hold but that with floating point types
it returns the smallest positive value. Makes it hard to write templates
dealing with ranges. Couldn't there be std::limits<double>::smallest ?

B) Sequence containers have an erase function that returns the next
iterator. Associative containers don't.

C) Overriding a non virtual function in a derived class, doesn't
require a diagnostic that the function is hidden.

D) A compiler is allowed to give a diagnostic in the case of C.
 
J

John Carson

Steven T. Hatton said:
No, this is not a troll

Perish the thought.

The reality is that C++ is likely to be obsolete long before there is any
chance of your list of desired changes being implemented. The next version
of the standard is still years away and won't come close to addressing your
wish list. The version after that, if there is one, will be another 10 years
or so further on, and it's anyone's guess what changes might be made. The
computing environment will have changed beyond recognition before there is
any chance of the preprocessor being abolished.

So what is the point of endlessly banging on about what you don't like about
C++? Learn it, live with it, and get on with it --- or use some other
language.
 
T

Tony

Also if
you are new to the technology field and want to become a developer, you
need to learn many techniques and languages. Do not stop and sit with
one language and framework/platform, learn everything you can.

Or instead of being a consultant of technology, be someone that can actually
build something with it. With C++, rarely do you have to look anywhere else.
All the time spent learning other languages and stuff doesn't make you as
valuable as one who can apply it to some domain, like scientific computing,
graphics/games, OLTP etc. Do survey the other stuff, but don't waste too
much time trying to learn everything and become too broad to apply anything
"professionally". (Sure, I could learn German, Spanish and Latin. But I find
English more than adequate for my purposes and I have better things to do!).

Tony
 
S

Steven T. Hatton

Kai-Uwe Bux said:
Steven said:
No, this is not a troll, and I am not promoting Java, C-flat, D, APL,
Bash,
Mathematica, SML, or LISP. A college teacher recently posted to this
newsgroup regarding her observation that there has been a significant
decline in the number of students opting to take courses in C++. I just
want to let people know what I believe are the biggest obstacles to C++
language acquisition, and what aspects of the language make it less
appealing than it could be.

None of these are integral to the core language. The typical selling
points for Java and Microsoft's Java-like pseudo-C++ are "garbage
collection"
and "no unsafe access (pointers)". I am convinced that neither of those
issues are weaknesses of C++. Both of these are actually strengths of
C++ in comparison to the competing languages. RAII forces the programmer
to know what he or she is really doing with resources, and leads to
cleaner,
more coherent code. Certainly pointers can result in problems if not
handled correctly. OTOH, the direct access to addressable memory enables
many optimizations and capabilities which the other languages have to
provide by modifying the language implementation (which is more than
likely
written in C++). There are plenty of programming practices which protect
against traditional buffer overrun problems, etc.

What I found most problematic when learning C++ were, roughly in order of
significance:
[snip]

Ok, and here is what I dislike most about C++ in no particular order:

a) 8.3.5/5, in particular the rule about initialization of const
references and the fact that one cannot bind temporaries to non-const
references.

Why on Earth would you want or expect such a thing? In general temporaries
are not even guaranteed to exists. The more requirements you place on
them, the more restrictions you place on the compiler to limit
optimization.
b) that typeid returns a by and large useless type_info object where it
could return a full-fledged type object that would allow for introspection
and allocation/construction of variables of that type.

That kind of thing takes a lot more infrastructure than the current model.
It would almost certainly violate the zero overhead rule. type_info is
extensible (has a virtual destructor), so you can implement your own
get_instance if you want it. Requiring that every type be default
constructible also places restrictions on the design of objects. The
functionality is really not useful enough to justify making it a
requirement for all types.
c) that I cannot overload the dot operator, e.g., so that I could have
smart references or _1.member_function() in lambda.

That has been proposed. I don't know what the status of the proposal is.
d) that C++ doesn't have virtual member templates.

How would that be useful? One of the biggest motivations for using
templates is to avoid the overhead of virtual function calls, and even of a
vtable in most cases.
e) that my beloved templates produce error messages that fill multiple
screens.

That is largely an implementation issue.
f) that the standard is worded according to the philosophy "when in doubt,
declare the behavior undefined".

Any other choice would place a requirement and/or restriction on the
implementation. For example, requiring an exception when any invalid
pointer is dereferenced would lead to extra clock cycles being spent for
every pointer access.
g) that the standard library components have too restrictive requirements,
e.g., list<T> requires the type T to be complete.

That's really a fundamental requirement of the language. list<T> is a type
which can be used to define objects. It must therefore be complete. There
are ways to use typedef to get around some of the order dependencies with
templates. What I would like are typedef templates.
h) that there is no integral type or typedef guaranteed to be long enough
to hold a void*, and that there is no useful conversion to integral types
for function and member function pointers.
Are you sure size_t does not qualify?
Here is a shorter list of minor nuisances:

A) that there is no guarantee that one can derive from standard
container/iterator classes.

What's to stop you?
B) that signed integral types make virtually no useful guarantees, and
that std::limits does not provide enough information to work around that
problem.

That has been under discussion. AAMOF, I raised that issue a long time ago
on comp.std.c++.
C) that there is no arbitrary precision / big integer class and no matrix
/ tensor template in the standard.

There are things I would want a lot more than a standard tensor. You can
implement such things without too much effort using std::valarray.
D) that there is no window / gui support in the standard.

That is not something that should be part of the core language or library.
Any given implementation would impose far too many requirements on
implementors, and would never satisfy the needs of a sufficient majority of
users to justify it. You can run X on every major platform, so you can use
any of the GUI tool kits that run under X. Qt is available for Windows,
Mac and (other) *nix. Mozilla/Netscape is written using a cross platform
widget kit, Gtk.
 
M

MC felon

If you dont like it you can start from scratch and build it from top to
bottom in C++... go try that in java (or wait you cant).

I like C++ and Java but they have their own purposes and uses. Also if
you are new to the technology field and want to become a developer, you
need to learn many techniques and languages. Do not stop and sit with
one language and framework/platform, learn everything you can.

Right now the three strongest skills that company's are looking for in
a dev is: C++ (still number one), Java and C#
SECONDED!! c++ rox! and next comes java!!!!! (and other languages).
 
E

Evan

Steven said:
Why on Earth would you want or expect such a thing? In general temporaries
are not even guaranteed to exists. The more requirements you place on
them, the more restrictions you place on the compiler to limit
optimization.

It's still better than creating a variable to contain the value you
want to pass into the function just because you can't pass in the
literal directly.

That's really a fundamental requirement of the language. list<T> is a type
which can be used to define objects. It must therefore be complete.

If the template only would refer to T* or T&s, then it wouldn't have to
be complete. For instance,
class Incomplete;

template <typename T>
class List {
T* head;
};

List<Incomplete> list;

I assumed that Kai-Uwe's complaint was about an example like that, in
which case it would be a "defect" IMO with the language. The problem
with that view is... the example works. GCC, ICC, and Comeau all
compile it.

There
are ways to use typedef to get around some of the order dependencies with
templates. What I would like are typedef templates.

I think there's a proposal for that too. I think that was one of the
"this is a likely addition" things in a presentation Stroustrup did a
couple years ago about C++0x.

What's to stop you?

The lack of a virtual destructor is at least fairly limiting. (I
remember hearing there's also a proposal to add versions of the STL
containers with virtual destructors.)

Evan
 
R

red floyd

Duane said:
A) std::limits<Any integral type>::min() returns the
minimum value the type can hold but that with floating point types
it returns the smallest positive value. Makes it hard to write templates
dealing with ranges. Couldn't there be std::limits<double>::smallest ?

I'm not sure this is a wart. Since since most floating reps (does the
Standard mandate IEEE-754?) use a separate sign bit, the minimum value
of a floating type is -std::limits<floating_point_type_t>::max().
 
E

Evan

red said:
I'm not sure this is a wart. Since since most floating reps (does the
Standard mandate IEEE-754?) use a separate sign bit, the minimum value
of a floating type is -std::limits<floating_point_type_t>::max().

I think the poster knows that.. what Kai-Uwe is saying is that you
can't just write std::limits::min() for the minimum value generically.
Which means that if you have a template that takes a type T and you
need to find the minimum value T can take on, you can't do it
generically, because std::limits<T>::min won't give it to you in all
cases.

It makes generic programming harder, NOT determining the minimum FP
value harder.

Evan
 
K

Kai-Uwe Bux

Steven said:
Kai-Uwe Bux said:
Steven said:
No, this is not a troll, and I am not promoting Java, C-flat, D, APL,
Bash,
Mathematica, SML, or LISP. A college teacher recently posted to this
newsgroup regarding her observation that there has been a significant
decline in the number of students opting to take courses in C++. I just
want to let people know what I believe are the biggest obstacles to C++
language acquisition, and what aspects of the language make it less
appealing than it could be.

None of these are integral to the core language. The typical selling
points for Java and Microsoft's Java-like pseudo-C++ are "garbage
collection"
and "no unsafe access (pointers)". I am convinced that neither of those
issues are weaknesses of C++. Both of these are actually strengths of
C++ in comparison to the competing languages. RAII forces the programmer
to know what he or she is really doing with resources, and leads to
cleaner,
more coherent code. Certainly pointers can result in problems if not
handled correctly. OTOH, the direct access to addressable memory
enables many optimizations and capabilities which the other languages
have to provide by modifying the language implementation (which is more
than likely
written in C++). There are plenty of programming practices which
protect against traditional buffer overrun problems, etc.

What I found most problematic when learning C++ were, roughly in order
of significance:
[snip]

Ok, and here is what I dislike most about C++ in no particular order:

a) 8.3.5/5, in particular the rule about initialization of const
references and the fact that one cannot bind temporaries to non-const
references.

Why on Earth would you want or expect such a thing?

This compiles:

#include <vector>
typedef std::vector<int> int_vector;
int main ( void ) {
int_vector iv ( 2000 );
int_vector().swap( iv );
}

This does not:

#include <vector>
typedef std::vector<int> int_vector;
int main ( void ) {
int_vector iv ( 2000 );
iv.swap( int_vector() );
}

The consequences range from minor nuisances to more serious issues: when I
return proxy classes instead of non-const references to members, the
temporary instances of these proxy classes cannot be passed to functions
properly, which leads to absurd constructions like swap() methods that take
their parameters by value or const reference. I ran into these issues
several times.
In general
temporaries
are not even guaranteed to exists. The more requirements you place on
them, the more restrictions you place on the compiler to limit
optimization.

Those temporaries that I do not bind to references can still be optimized
away.

That kind of thing takes a lot more infrastructure than the current model.
It would almost certainly violate the zero overhead rule. type_info is
extensible (has a virtual destructor), so you can implement your own
get_instance if you want it.

Nope, you can't: it lacks the protected members you would need to do that.
Requiring that every type be default
constructible also places restrictions on the design of objects. The
functionality is really not useful enough to justify making it a
requirement for all types.

1) I was not proposing that. What I meant is something like:

typeof( some_expression ) dummy;

should allocate a variable dummy if possible. There would be an exception
thrown if the type does not allow for default construction.

2) How do you know how useful this feature is. Maybe, there is a little lack
of imagination on your part.

That has been proposed. I don't know what the status of the proposal is.


How would that be useful?

For instance, it can help with the double dispatch problem.

One of the biggest motivations for using
templates is to avoid the overhead of virtual function calls, and even of
a vtable in most cases.

Among my motivations for templates, this item does not even occur at all;
and I am doing template code all the time. Very likely, your statement is
made from the point of view of OO where templates may enter the picture as
an optimization hack.

That is largely an implementation issue.

Not really: the instantiation trace is indeed by and large necessary to
locate the error (at least there are obscure errors that you would not spot
without it). The compiler can format it nicely, but trimming the trace
correctly is probably equivalent to the halting problem.

Any other choice would place a requirement and/or restriction on the
implementation. For example, requiring an exception when any invalid
pointer is dereferenced would lead to extra clock cycles being spent for
every pointer access.

I do not complain about judicious use of undefined behavior in the language
specs. However, C++ is going overboard with it.

The particular case of unchecked pointer access I find easy to deal with: I
have a dummy smart pointer class that does nothing more than adding
debugging support, e.g., an assert in operator* and operator->. When the
assert gets defined away, there is no difference in performance but for
debugging I get my error messages.

That's really a fundamental requirement of the language. list<T> is a
type
which can be used to define objects. It must therefore be complete.

Maybe you misread what I wrote. Anyway, std::list<T> can be complete for
incomplete T. In fact, all implementations of std::list<> that I know
already do this trick (except, maybe, g++ with concept checks turned on).
It's just that the standard does not make it a requirement.
There are ways to use typedef to get around some of the order dependencies
with templates.

Not this one.
What I would like are typedef templates.

Me too. And I also want partial specialization for function templates.

Are you sure size_t does not qualify?

Yes: there is no guarantee that sizeof( void* ) <= sizeof( std::size_t ).

What's to stop you?

There is a trick preventing derivation (making slick use of a virtual base).
The standard makes no promise whatsoever that standard classes are not
implemented using that trick. Again, all implementations known to man allow
deriving from standard containers / iterators, and for good reasons; but
formally an implementation is allowed to reject code relying on this.

That has been under discussion. AAMOF, I raised that issue a long time
ago on comp.std.c++.


There are things I would want a lot more than a standard tensor. You can
implement such things without too much effort using std::valarray.

If you do it "without too much effort", you get a useless toy. To do it
right requires some serious work. This is an area where performance matters
tremendously. Since there is compiler magic available to implementors that
is not available to programmers, I think, this is a good candidate for an
extension.

That is not something that should be part of the core language or library.
Any given implementation would impose far too many requirements on
implementors,

Nope. This just becomes a quality of implementation issue: if an implementor
is too lazy to implement the window classes, just make every constructor
throw. Then all members can be implemented as do-nothing methods. Since the
standard cannot require the existence of a screen, we have to allow for
allocation of screen resources to fail anyway.
and would never satisfy the needs of a sufficient majority
of users to justify it.

That is debatable.
You can run X on every major platform, so you can use
any of the GUI tool kits that run under X. Qt is available for Windows,
Mac and (other) *nix. Mozilla/Netscape is written using a cross platform
widget kit, Gtk.

That is a little bit missing the point: I was not complaining that there is
no window / gui support for C++. However, standardization brings more
benefits than mere existence.



Best

Kai-Uwe Bux
 
K

Kai-Uwe Bux

Evan said:
It's still better than creating a variable to contain the value you
want to pass into the function just because you can't pass in the
literal directly.



If the template only would refer to T* or T&s, then it wouldn't have to
be complete. For instance,
class Incomplete;

template <typename T>
class List {
T* head;
};

List<Incomplete> list;

I assumed that Kai-Uwe's complaint was about an example like that, in
which case it would be a "defect" IMO with the language. The problem
with that view is... the example works. GCC, ICC, and Comeau all
compile it.

I am thinking of examples like this:

#include <list>

struct tricky {

std::list<tricky> recursive;

};

int main ( void ) {
tricky dummy;
}

This compiles fine with g++ and Comeau, but I can make it fail when I build
g++ with concept checks. The code is not _required_ to work and it is not
_required_ to fail.
I think there's a proposal for that too. I think that was one of the
"this is a likely addition" things in a presentation Stroustrup did a
couple years ago about C++0x.



The lack of a virtual destructor is at least fairly limiting. (I
remember hearing there's also a proposal to add versions of the STL
containers with virtual destructors.)

The lack of a virtual destructor won't stop me. However, as far as I can
tell,

#include <vector>
class X : public std::vector<int>::iterator {};

is not _required_ to compile.


Best

Kai-Uwe Bux
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top