What has C++ become?

K

Kai-Uwe Bux

Juha said:
I disagree. Using longer keywords and notation does not make the code
unclear, but all the contrary: It makes the code more understandable and
unambiguous. When you try to minimize the length of elements what you
end up is basically an unreadable obfuscated regexp.

Yes and no. I really like the verbosity of Modula 2 in control flow as
opposed to the use of "{" and "}". However, when it comes to template
template parameters, I have trouble getting a reasonable layout to work
simply because its using too much horizontal space. A baby case example is
something like

typedef typename
allocator_type::template rebind< ListNode >::eek:ther node_allocator;

Regardless of where I put the line break, it always looks somewhat
suboptimal.

I think that your suggestion itself is a perfect example of that:


Yes, that uses less characters than "table.push_back(5);". However,
why would that be any clearer and more understandable? On the contrary,
it's more obfuscated.

Well, that depends, too. In D, "~" denotes concatenation. It makes perfect
sense, not to use "+" for that, and "~" feels somewhat right. Now, with
that convention in place, table ~= 5 is not obfuscated at all.

I have never understood the fascination some people (and almost 100%
of beginner programmers) have with trying to minimize the size of their
source code. They will sometimes go to ridiculous extents to try to make
the code as short as possible, at the cost of making it completely
obfuscated.

On that, I agree. But that does by no means imply that the syntax of C++ is
doing a good job in supporting clear and understandable coding of template
stuff.

Brevity does not improve readability, but all the contrary.

Overboarding use of horizontal space making it hard to put line breaks in
appropriate places also does not improve readability.


Best

Kai-Uwe Bux
 
J

James Kanze

You can safely ignore this geek style 'template programming'
because it will never reach the mundane area of real-world
programming.

First, you can't ignore anything, because you never know where
it will crop up. And like most things, it will be more or less
readable, depending on who wrote it.

What is true is that at the application level, there is very
little need for meta-programming; it is mostly used in low level
libraries (like the standard library). What is also true is
that some of its more extreme use does push readability, even
when written by an expert (but there are also some simple,
everyday idioms which even average programs should be able to
master). And what is certainly true is that it is being used
(probably too much, even in places where it isn't needed).
 
J

James Kanze

Juha said:
Maybe you think using <> makes template code "a mess"? I don't
understand why.
It's because of the parsing ambiguities that come from using < > as a
parameter delimiter.
Is this somehow unclear:
std::vector<int> table;
table.push_back(5);
What's so unclear about that? I think it's perfectly clear
and legible code. How else would you want it to be?
It's the wordiness of it. If the code gets more complicated
than such trivial examples, it gets rather hard to visualize.
I would want it to use a much more compact notation, like
maybe:
int[] table;
table ~= 5;
The problem with compact notation is that they can only fill a very
small number of cases.

The problem with compact notation is that it quickly leads to
obfuscation. Witness perl and APL. Many of the problems with
C++ today is that there was an attempt to make the notation too
compact in the past. Things like:
int*p;
int a[10];
rather than:
variable p: pointer to int ;
variable a: array[ 10 ] of int ;
The result is a declaration syntax which causes untold problems,
not just to human readers, but also to compilers.
 
J

James Kanze

I disagree. Using longer keywords and notation does not make
the code unclear, but all the contrary: It makes the code more
understandable and unambiguous. When you try to minimize the
length of elements what you end up is basically an unreadable
obfuscated regexp.

Yes. Typically, perl looks more like transmission noise that it
does a program.

In the (now distant) past, there was an argument for reducing
the number of characters. If you've ever heard a listing output
to a teletype, you'll understand. But I know of no programmer
today who develops code on a teletype. (But then, everyone I
know is in either western Europe or North America. Perhaps in
less priviledged regions.)
I think that your suggestion itself is a perfect example of that:
Yes, that uses less characters than "table.push_back(5);".
However, why would that be any clearer and more
understandable? On the contrary, it's more obfuscated.

From the looks of things, Walter would like APL. A language
known for read only programs.
I have never understood the fascination some people (and
almost 100% of beginner programmers) have with trying to
minimize the size of their source code. They will sometimes go
to ridiculous extents to try to make the code as short as
possible, at the cost of making it completely obfuscated.
Brevity does not improve readability, but all the contrary.

Brevity, correctly applied, can improve readability. As my high
school English teacher used to say, "good writing is clear and
concise". The problem with verbosity, however, isn't the lenght
(in characters) of the words (tokens). The problem with much
template programming is that it deals with several different
levels at the same time, each with it's own vocabulary, so you
need a lot more words. And it's a fundamental problem; I don't
think that there is a real solution.
 
M

Matthias Buelow

Erik said:
int[] table;
table ~= 5;

The natural interpretation of the above would in C++ be "table != 5".
Assigning non-intuitive meanings to operators is much worse than a lack
of compactness. If you really want an operator use either += or <<.

I agree; I associate some kind of negation with ~, not concatenation.
For ~=, I'd probably go with the C-style interpretation of = ... ~, or
interpret it as some kind of congruence operator.
 
V

Vidar Hasfjord

[...]
I don't believe that replacing operators with
long words makes code clearer - didn't Cobol demonstrate that?

In my view, the essential observation is that the keywords here, 'to'
and 'of', highlights an irregularity in the language; constructs
reserved for special built-in features. Whether such irregularities
are words or operators doesn't matter.

For example, I find the C++ type constructor operators for arrays ([])
and pointers (*) just as unnecessary and cluttering. They were needed
when C was invented, but now C++ has templates for parameterized
types. Arrays are parameterized types. So are pointers. So an ideal
regular language would use the same syntax:

pointer [int] p;
array [int, 10] a;
my_2d_array [int, int, 10, 10] m;

This also allows you to reserve square brackets for all parameterized
compile-time structures (templates). That would eliminate parser
irregularities with angle brackets. Then use Fortran style syntax for
indexing, i.e. p (0), p (1). Interestingly, this extends elegantly to
multi-dimensional arrays, m (0, 1), while the current C++ square
bracket operator does not; since it accepts only one parameter. It
seems that, with regularity, less is more.

These few syntax improvements along with obolishing some of the most
problematic type system irregularities (such as array decay and other
unwise conversion rules) would go a long way in making C++ a simpler
language both syntactically and semantically.

Of course, it wouldn't be C++ anymore; but hey, why not define "C++
Level 2" and some migration path via interoperability features?
Modules, when they are introduced to the language, may make this more
feasable, perhaps.

Regards,
Vidar Hasfjord
 
V

Vidar Hasfjord

[...]
I have trouble getting a reasonable layout to work
simply because its using too much horizontal space. A baby case example is
something like

  typedef typename
  allocator_type::template rebind< ListNode >::eek:ther node_allocator;

Getting rid of the redundant 'typename' and 'template' keywords would
help a lot. As I understand it a cleaner syntax and the use of
concepts would allow the expression to be inferred without these.

The other fundamental problem with C++ meta-functions is that it is
based on this cumbersome conventions:

typedef meta_function <arg1, arg2>::result r;

The ideal syntax would be:

alias r = meta_function <arg1, arg2>;

The problem is to distinguish between a meta-function reference and
the type (result) that it produces. (Aside: This is the same problem
as for regular functions; distinguishing the use of the function as a
function call that evaluates to the result and the value of the
function itself; which in C++ decays to a function pointer.)

It seems that the new C++09 alias syntax provides what's needed:

template <typename T1, typename T2>
alias meta_function = ...;

Are the full gamut of template features available for templated
aliases? Such as partial specialization etc.?

Regards,
Vidar Hasfjord
 
K

kwikius

For example, I find the C++ type constructor operators for arrays ([])
and pointers (*) just as unnecessary and cluttering. They were needed
when C was invented, but now C++ has templates for parameterized
types. Arrays are parameterized types. So are pointers. So an ideal
regular language would use the same syntax:

  pointer [int] p;
  array [int, 10] a;
  my_2d_array [int, int, 10, 10] m;

Interesting dude ... :)


regards
Andy Little
 
K

kwikius

  typedef meta_function <arg1, arg2>::result r;

The ideal syntax would be:

  alias r = meta_function <arg1, arg2>;

I've been toying about with this stuff myself. I've been looking at LL
grammars for a C++ like language without the crud.

AFAICS typename is useful because the parser needs to know that a name
is a type within a template and it solves the problem in a nice LL
way. The problem is that it isnt really regular in C++ (eg also have
typedef which is rather horrible from C useage too)

In my doodlings a metafunction invocation has the same syntax as a
function:

typename r = meta_function(arg1,arg2);

Note that the context provided by typename means that initaliser must
be a type not value. In fact a metafunction can be an ordinary
function where it just gives returntype. (Can though just define the
metafunction) Also works with operators;

typename A = ...;
typename B = ...;
typename C = ..;

typename plus_type = A + B + C;

For legibility you can add an optional (or maybe required for clarity)
prefix:

typename r = typefn metafunction(arg1,arg2);

typename plus_type = typefn A + B + C;


regards
Andy Little
 
N

Noah Roberts

James said:
First, you can't ignore anything, because you never know where
it will crop up. And like most things, it will be more or less
readable, depending on who wrote it.

What is true is that at the application level, there is very
little need for meta-programming; it is mostly used in low level
libraries (like the standard library).

Well, first of all, I don't think that the standard library, where it
actually makes use of generic/meta programming techniques, is "low
level". It is very much application level - stacks, lists,
vectors...this isn't hardware talking stuff. There is nothing low level
about abstract data types. It is exactly the opposite of low level in
my opinion.

Second, I disagree that there's little need for it in the application
level programming. We, where I work, actually use it a moderate amount
and to great advantage. For instance, we are an engineering firm and
use a data type that uses metaprogramming techniques to provide type
safe dimensional analysis. Since adopting this it has already saved us
numerous man hours in debugging.

We use boost::units and some other stuff that I wrote on top of it.
Other areas it is used is in a variety of generic functions that use
enable_if to choose or disqualify template instantiations.

So as one that is not afraid of TMP and uses it *in the application
layer* I really have to disagree with those claiming it has no place there.
What is also true is
that some of its more extreme use does push readability, even
when written by an expert (but there are also some simple,
everyday idioms which even average programs should be able to
master).

Which is why I recommend getting and reading the TMP book by Abrahams
and Gurtovoy. Knowing the concepts that they developed enable one to
understand TMP much better, assuming the developer is using such
concepts and hasn't written their own. Even then, there's really only
so many ways you can do TMP and so learning theirs is a good step toward
understanding anyone's, including the STL that uses blobs.

It's a different kind of code. It isn't easy to do. But it isn't
readability that is the problem here, it's understanding that style of
language. It is a skill that all C++ developers should attempt to
become familiar with for it will only get more and more common as more
and more people adopt and refine the generic programming paradigm in
C++. Many of the new language features were put in specifically FOR
this kind of development.

And what is certainly true is that it is being used
(probably too much, even in places where it isn't needed).

And it is also certainly true that it is NOT being used in many places
where it should be.
 
N

Noah Roberts

Walter said:
I've had many programmers tell me that their style of programming is
based on how much they can see on their screens. As screens have gotten
bigger, their mental "unit of code" has increased to match. I know I
used to make all my functions fit in 24 lines or less, now 60 lines is
typical.

That is way too many. It's not about what will fit on your screen, but
what fits in the brain in one go. Long functions do not.
Take a look at Scott's slides again. I don't see any reasonable way of
formatting it to look decent on a screen.

Well, I prefer something more like so:

template<typename S, typename T> // compute index of T in S
struct IndexOf
: mpl::distance
<
typename mpl::begin said:
{};

But to each his own. Neither is particularly difficult to understand.
 
E

Erik Wikström

[...]
I don't believe that replacing operators with
long words makes code clearer - didn't Cobol demonstrate that?

In my view, the essential observation is that the keywords here, 'to'
and 'of', highlights an irregularity in the language; constructs
reserved for special built-in features. Whether such irregularities
are words or operators doesn't matter.

For example, I find the C++ type constructor operators for arrays ([])
and pointers (*) just as unnecessary and cluttering. They were needed
when C was invented, but now C++ has templates for parameterized
types. Arrays are parameterized types. So are pointers. So an ideal
regular language would use the same syntax:

pointer [int] p;
array [int, 10] a;
my_2d_array [int, int, 10, 10] m;

This also allows you to reserve square brackets for all parameterized
compile-time structures (templates). That would eliminate parser
irregularities with angle brackets.

Those have been removed in the next standard already, no need for square
brackets.
Then use Fortran style syntax for
indexing, i.e. p (0), p (1). Interestingly, this extends elegantly to
multi-dimensional arrays, m (0, 1), while the current C++ square
bracket operator does not; since it accepts only one parameter. It
seems that, with regularity, less is more.

I seriously doubt that there is any technical problem with allowing the
[] operator to accept more than one argument, it seems to me more like
an arbitrary decision once made which none bothers to challenge.
 
B

Bo Persson

Erik said:
Then use Fortran style syntax for
indexing, i.e. p (0), p (1). Interestingly, this extends elegantly
to multi-dimensional arrays, m (0, 1), while the current C++ square
bracket operator does not; since it accepts only one parameter. It
seems that, with regularity, less is more.

I seriously doubt that there is any technical problem with allowing
the [] operator to accept more than one argument, it seems to me
more like an arbitrary decision once made which none bothers to
challenge.

It has been challenged, but not enough.

I have seen published search results by people trying to find code
using an overloaded comma operator inside the brackets. None found, if
I remember correctly.

However, both C and C++ already have a defined meaning for a[x,y],
though pretty useless. The proposers of a new meaning just haven't
been persistent enough, to convince a majority.

Recent radical changes to the keyword 'auto' might have set a new
precedent though. :)


Bo Persson
 
N

Noah Roberts

Walter said:
Suppose we could write it as:

int IndexOf(S, T)
{
return distance(begin(S), find(S, T));
}

Would you prefer the latter? I sure would.

I really don't see what that has to do with anything unless you want to
just bitch and moan, pretending that TMP is the same as runtime programming.
 
N

Noah Roberts

Bo said:
I have seen published search results by people trying to find code
using an overloaded comma operator inside the brackets. None found, if
I remember correctly.

There was a post of one that made use of a special type...MagicInt if I
recall correctly. Took place in a discussion on () vs. [] for matrix
abstractions a year or two ago here in this group.
 
V

Vidar Hasfjord

[...]
I don't know of a property of compile time programming that requires it
to be more complex than runtime programming.

That's a good point. But an interesting follow-up question to that is:
Should it be different?

Having thought about this superficially my intuition is that the
compile-time domain and the runtime domain calls for different
programming paradigms. In a way I think C++ just stumbled upon the
holy grail: It found the ideal domain for functional programming
languages; the compile-time domain.

Meta-programming operates in a formal domain; the domain of the type-
system of the language. Functional programming is a perfect fit here
as it is suited for formal proofs etc. Hence I don't think imperative
features, such as mutating constructs and side-effects, belong at
compile-time.

C++ has introduced a new era where the compiler is an execution
platform in itself. So the challenge for future language development
is to make the meta-language; the functional programming language that
runs in the compiler, optimal both for programmer expressiveness and
clarity and for efficient compile-time execution.

Regards,
Vidar Hasfjord
 
V

Vidar Hasfjord

[...]
I've been toying about with this stuff myself. I've been looking at LL
grammars for a C++ like language without the crud.

That is very interesting. Do you have any published work, or links to
other work in this area, that I can look at?

I am only aware of SPECS (Significantly Prettier and Easier C++
Syntax) by Werther and Conway. I think that syntax could be made even
simpler by dropping the type constructor operators for pointers and
arrays. That would free the square brackets for template use (SPECS
uses <[]>; unambiguous, but verbose). It is still a good effort.

Regards,
Vidar Hasfjord
 
K

kwikius

[...]
I've been toying about with this stuff myself. I've been looking at LL
grammars for a C++ like language without the crud.

That is very interesting. Do you have any published work, or links to
other work in this area, that I can look at?

I havent got anything publishable on my own doodlings, however for LL
grammar I seriously recommend SLK

http://home.earthlink.net/~slkpg/

It has nice properties. Various languages supported.. The actions are
largely separated from the grammar source and this puts more emphasis
on the grammar than semantics, which should I conjecture lead to a
cleaner grammar than e.g Bison. Also grammar source files are nice and
compact to pass around for discussion...
I am only aware of SPECS (Significantly Prettier and Easier C++
Syntax) by Werther and Conway. I think that syntax could be made even
simpler by dropping the type constructor operators for pointers and
arrays. That would free the square brackets for template use (SPECS
uses <[]>; unambiguous, but verbose). It is still a good effort.

I will certainly take a look. Unfortunately I have a lot of other work
currently so I can't spend the time I would like to on it.... but IMO
it has to be done as I have hit the C++ wall (e.g TMP complexity long
compile times etc. I think that will only get worse with C++0x
Concepts (which also dont seem to play too well with TMP).

regards
Andy Little
 
M

Matthias Buelow

Vidar said:
C++ has introduced a new era where the compiler is an execution
platform in itself.

This isn't anything new; Lisp macros have been doing that for uhm..
decades, if I'm right. A C++ template is a special kind of compiler
macro where the expansion is controlled by the type parameters, whereas
a Lisp macro, for example, can use the full language to produce code to
substitute in its place, by any computation conceivable (including side
effects). I agree that compiler macros (including C++ templates) are a
useful tool for extending the language.
 
J

James Kanze

I've had many programmers tell me that their style of
programming is based on how much they can see on their
screens. As screens have gotten bigger, their mental "unit of
code" has increased to match. I know I used to make all my
functions fit in 24 lines or less, now 60 lines is typical.

Help. I find that if a function is more than about 10 lines,
it's a warning sign that it's getting too complex. There are
exceptions, of course. A function which consists of a single
switch statement with a lot of entries, for example. The real
criteria is complexity, but in my own work, I find that ten
lines generally means that its time to watch out.
Take a look at Scott's slides again. I don't see any
reasonable way of formatting it to look decent on a screen.

That's not my argument. I'm certainly not going to argue that
C++ syntax is clear, concise or elegant. Just that less isn't
always better either---had there been a little more wordiness in
C's declaration syntax, we'd have a lot less problems today, for
example.
Since the D programming language looks nothing like APL (or
Perl), I don't understand your comment at all.

Humor, mostly. But when you start arguing that something is
better just because it requires less characters to write, you're
definitly moving in the direction of APL.
Also, the way arrays work in D, which includes using the ~ and
~= operators, are frequently cited by D users as one of the
main reasons they like D. Do you really believe that ~ as
concatenation and ~= for append is "obfuscation" ?

In C++, it definitely would be. In another language... I don't
know. I can see the need for a generic concatenation operator
(rather than just overloading +), and I don't see any good
spelling for it (unlike "or" for |). And it's probably frequent
enough that you can live with some arbitrariness (i.e. it not
being based on established mathematical use, like +). So I
guess it would fit in like << does for output in C++.

But even then, only as a special case. I certainly hope you
don't try to define single character special operators for every
single operation on a container.
It's both the length and the fact that there are so many
tokens needed to be strung together to perform basic
operations. What you're trying to accomplish gets lost in all
the < > and ::.

I guess it depends on what you are trying to accomplish. That's
certainly the case for TMP. And I have nothing against some
shorter syntax, per se, if it's reasonably readable. Note,
however, that part of the added length comes from longer names
and namespaces. But I would certainly prefer vector< string >
to v<s>. I don't have a simple solution; for better or for
worse, we're dealing in a larger solution space than in the old
days, the amount of information that needs to be communicated
has gone up significantly, some redundancy is necessary for
human comprehension, and the result does require more characters
(each of which can only hold so much information).
 

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

Forum statistics

Threads
473,997
Messages
2,570,240
Members
46,830
Latest member
HeleneMull

Latest Threads

Top