What has C++ become?

J

James Kanze

I'm trying to show that complicated syntax is not fundamental
to TMP.

Isn't part of the problem is that TMP is embedded in a runtime
programming language, and cannot use the natural syntax for many
of its constructs because that has already been pre-empted by
the runtime language?
I don't know of a property of compile time programming that
requires it to be more complex than runtime programming.

Perhaps the complexity is partially due to the fact that the two
are not rigorously separated, so you need special (and IMHO
awkward) syntax for the TMP, so that the compiler and the reader
can know what is compile time, and what is runtime.
 
K

kwikius

Walter Bright said:
That means that the programmer needs to learn two languages instead of
one. To ask for this one must have some pretty compelling benefits of it
to justify it.

library versus application writing
I don't understand why, for instance:

int foo(int x)
{
x = 3 + x;
for (int i = 0; i < 10; i++)
x += 7;
return x;
}

is inappropriate for compile time execution. Of course, it could be
rewritten in FP style, but since I'm programming in C++, why shouldn't
straightforward C++ work?

It would potentially make a type mutable (different) in different
translation units I think.

regards
Andy Little
 
V

Vidar Hasfjord

This isn't anything new;

True, that statement of mine was sloppy and incorrect. It should read
"Template meta-programming has brought C++ into a new era...". I was
thinking narrowly about the evolution of C++ and compiling C++
programs.
Lisp macros have been doing that for uhm.. decades, if I'm right.

Yes, and Lisp's powerful yet small and regular language definition
should be an inspiration to every programming language designer.

Regards,
Vidar Hasfjord
 
V

Vidar Hasfjord

That means that the programmer needs to learn two languages instead of
one. To ask for this one must have some pretty compelling benefits of it
to justify it.

I look at it as two paradigms instead of two languages; the functional
paradigm and the imperative paradigm. C++ supports both; as does D; so
I'm sure you agree that's a good thing.

The question is whether all features (paradigms) of the language
should be available both for meta-programming and ordinary
programming. There has been work done on C++ extensions that allows
the full language for meta-programming (see Metacode by Vandevoorde),
but I lean towards restricting compile-time processing to the side-
effect free parts only, i.e. a functional subset.
I don't understand why, for instance:

int foo(int x)
{
x = 3 + x;
for (int i = 0; i < 10; i++)
x += 7;
return x;
}

is inappropriate for compile time execution.

Here I assume that you actually propose a very limited subset of
imperative features for compile-time processing; not that the whole
language should be available for processing at compile-time. A subset
of imperative features can be supported, as seen by constexpr function
in C++09 and by CTFE in D, but they are limited and required to live
by the rules of functional programming. For example, compile-time
functions must be 'pure', ie. the result must only depend on the
arguments, the function can have no side-effects and no state can
escape the function. I intuitively think this is good.

Or did you actually mean that you think the ideal would be something
akin to Metacode?
Furthermore, because every step in evaluating TMP requires the
construction of a unique template instantiation, this puts some rather
onerous memory and time constraints on doing more complicated things
with TMP. Perhaps these are merely technical limitations that will be
surmounted by advancing compiler technology, but I just don't see how
the result could be better than thousands of times slower than executing
the equivalent at run time.

Yes, these are the challenges I alluded to in my post. While limited
imperative features such as CTFE can ease some of this, I think C++
compilers will start looking more like execution environments for
functional languages as they evolve to handle meta-programs
efficiently. A lot of work on efficient processing of functional
languages has been done with good results. How feasable it is to bring
the results of this work into the construction of a C++ compiler I
don't know; but I can imagine the scale of the challenge.

Regards,
Vidar Hasfjord
 
P

Pascal J. Bourguignon

Walter Bright said:
I don't understand why, for instance:

int foo(int x)
{
x = 3 + x;
for (int i = 0; i < 10; i++)
x += 7;
return x;
}

is inappropriate for compile time execution. Of course, it could be
rewritten in FP style, but since I'm programming in C++, why shouldn't
straightforward C++ work?

First, notice that nothing prevents a C or C++ compiler to notice that
foo is a pure function, and therefore that any call such as:

int y=foo(42);

can be executed at compilation time.


The real reason why you would want to have some code executed at
compilation time is really to do metaprogramming.

Why code such as the above is inappropriate for compile time, in blub
languages, is because the types and data structures available in those
languages ARE NOT the types and data structure used by the compiler.

Well, you could 'try' to use string^W oops, there's no string data
type in C. Ok, let's try to use std::string in C++:

std::string genFun(std::string name,std::string body){
std::eek:stringstream s;
s<<"void "<<name<<"(){"<<endl;
s<<"cout<<\"Entering "<<name<<"\"<<endl;"<<endl;
s<<body<<endl;
s<<"cout<<\"Exiting "<<name<<"\"<<endl;"<<endl;
s<<"}"<<endl;
return(s.str());
}

and now we'd need some way to hook this function into the compiler,
let's assume a keyword 'macro' do do that:

macro genFun("example","cout<<\"In example function.\"<<endl;")

this would make the compiler run the expression following the keyword,
and replace the macro and expression with the resulting string, and
interpreting it in place.

Not very nice, is it.

What you are really longing for is Lisp with its s-expressions...

Regardless of the merits of FP programming, regular C++ programming is
not FP and it is not necessary for compile time evaluation to be FP.

Indeed, compiler hooks (macros) and programming style are totally orthogonal.

C++ has opened the door on that, I agree. Where I don't agree is that
C++ has stumbled on the ideal way of doing compile time programming,

That's the less that can be said about it...
or that FP is ideal for it, or that compile time programming should be
in a different language than runtime programming.

I am not an expert in C++ TMP. But when I do examine examples of it,
it always seems like a lot of effort is expended doing rather simple
things.
Indeed.


Furthermore, because every step in evaluating TMP requires the
construction of a unique template instantiation, this puts some rather
onerous memory and time constraints on doing more complicated things
with TMP. Perhaps these are merely technical limitations that will be
surmounted by advancing compiler technology, but I just don't see how
the result could be better than thousands of times slower than
executing the equivalent at run time.

Well, technically, since the solution has been know for about 50
years, it's not technical limitations, but psychological ones.
 
J

James Kanze

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.

It's not talking to the hardware, but it is still very low
level. A vector is not (usually) an application level
abstraction, but rather a tool used in application level
abstractions.
There is nothing low level about abstract data types. It is
exactly the opposite of low level in my opinion.

It's about the lowest level you can get. What's below it?
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.

But is the meta-programming in the application itself, or in the
lower level tools you use to implement it? (Not that I would
expect much metaprogramming in type safe dimensional analysis.)
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.

You can't really use templates too much in the application layer
anyway, because of the coupling they induce (unless all of your
compilers support export). And the whole point about being the
application level is that it is specific to the application;
it's not generic. What makes code the application level is that
it deals with concrete abstractions, like ClientOrder or
BookingInstruction (currently) or IPAddress (where I was
before). Just the opposite of template based generics.
 
V

Vidar Hasfjord

Vidar Hasfjord wrote:
[...]
I think that a subset approach is fine, but a different language
approach is not. For example, in C++, you cannot write a factorial
function that works at both compile time and run time.

I agree CTFE is convenient. I view it as part of the reasoning
abilities of the language that allows ordinary code to cross into the
compile-time domain. My observation is that code can only cross into
the compile-time domain when it adheres to principles of functional
programming; that it's output is solely dependent on its input and
that it has no external side-effects.

CTFE can't do computation on compile-time entities such as types. To
make imperative meta-programming pervasive you would need further
extensions to the language (such as Metacode).
I don't know anything about Metacode.

Metacode is an experimental extension to C++ to allow imperative meta-
programming and reflection. I don't think it was ever formally
proposed, but you can find a presentation at the ISO site:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1471.pdf

Regards,
Vidar Hasfjord
 
V

Vidar Hasfjord

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 agree that meta-function applications should look more like
traditional function applications. I believe C++09 will allow this
short and sweet style:

template <typename S, typename T>
using index_of = distance <begin <S>, find <S, T>>;

("Template aliases for C++", N2258)

Regards,
Vidar Hasfjord
 
M

Michael DOUBEZ

Juha Nieminen a écrit :
OTOH, multiplication of matrices is not commutative, yet it may make
sense to still support the * operator for matrix types...

But multiplication is not expected to be commutative other the matrix
group (or other non-Abelian rings). In math, the + sign is reserved for
commutative operations.
 
N

Noah Roberts

James said:
But is the meta-programming in the application itself, or in the
lower level tools you use to implement it?

Well, since you are going to assert an arbitrary point of separation
between the two, seemly generated solely to and dependent on your
conclusion, obviously only main() counts as application programming and
no, it's not a template meta-program.
(Not that I would
expect much metaprogramming in type safe dimensional analysis.)

I would suggest you go look at boost's, and other versions like Quan, then.

You can't really use templates too much in the application layer
anyway, because of the coupling they induce (unless all of your
compilers support export). And the whole point about being the
application level is that it is specific to the application;
it's not generic. What makes code the application level is that
it deals with concrete abstractions, like ClientOrder or
BookingInstruction (currently) or IPAddress (where I was
before). Just the opposite of template based generics.

Hehehe, where do you get this stuff??

* templates induce coupling? :p
* IPAddress is "application specific"? :p
* You don't use templates in the application layer? :p
 
N

Noah Roberts

Walter said:
I think that a subset approach is fine, but a different language
approach is not. For example, in C++, you cannot write a factorial
function that works at both compile time and run time.

I think that would only introduce confusion, which is already there,
about the difference between the compiler program and the one the
compiler is compiling. Having a strong split, conceptually and
practically, between the two is important.

Furthermore, meta-programing is not conducive to the language proper (as
has been explained). This means that to make them the same language you
would need to push toward the meta-programing model, not the other way.
Personally, I don't want to have to write THAT much code in that
manner. If I did I'd be using LISP or something.
 
J

Jerry Coffin

[ ... ]
But multiplication is not expected to be commutative other the matrix
group (or other non-Abelian rings). In math, the + sign is reserved for
commutative operations.

Not so -- a group is defined over an operation. If that operation is not
commutative, the group is non-Abelian. It may be true that study of non-
Abelian groups tends more often to look at multiplication than addition,
but it is not true that the + sign is reserved for commutative
operations. It's often true (probably far more often than not) but not
always.
 
P

Pascal J. Bourguignon

Noah Roberts said:
I think that would only introduce confusion, which is already there,
about the difference between the compiler program and the one the
compiler is compiling. Having a strong split, conceptually and
practically, between the two is important.

As has been shown by 50 years of metaprogramming in lisp.

Furthermore, meta-programing is not conducive to the language proper
(as has been explained). This means that to make them the same
language you would need to push toward the meta-programing model, not
the other way. Personally, I don't want to have to write THAT much
code in that manner. If I did I'd be using LISP or something.

Why not?

Why would you want to automatize the job of accountants or graphists,
but not your own?
 
J

James Kanze

Well, since you are going to assert an arbitrary point of
separation between the two, seemly generated solely to and
dependent on your conclusion, obviously only main() counts as
application programming and no, it's not a template
meta-program.
I would suggest you go look at boost's, and other versions
like Quan, then.

And where would they use meta-programming, except for
obfuscation? (Not all templates are metaprogramming.)
Hehehe, where do you get this stuff??

Practical experience.
* templates induce coupling? :p

And how, unless all of your compilers support export.
* IPAddress is "application specific"? :p

It was in my application (dynamical allocation of IP addresses).
* You don't use templates in the application layer? :p

They've been banned at the higher levels in most coding
guidelines I've seen, because of the coupling problems they
induce.

It's just a question of good software engineering. You don't
introduce complexity (or coupling) where it isn't needed. You
don't throw in or use features just because they're the in
thing. Templates (like many other things) have a cost. With
most current compilers, part of that cost is a significant
increase in coupling, which becomes very expensive the higher up
toward the application level you go. Whereas the benefits of
templates are mostly present at the lower levels. As always,
one might find some exceptions, but the in general, templates
aren't used much at the application level when engineering
criteria are used to decide.
 
K

kwikius

They've been banned at the higher levels in most coding
guidelines I've seen, because of the coupling problems they
induce.

Interesting. std::string being a typedef for a class template, similarly
std::vector, std::list , std::map ,set

Are all these banned?

regards
Andy Little
 
N

Noah Roberts

James said:
And how, unless all of your compilers support export.

Header dependencies and code coupling are very, very different things.
Templates *reduce* coupling.
 
N

Noah Roberts

Pascal said:
Why not?

Why would you want to automatize the job of accountants or graphists,
but not your own?

You have a point, and I do where I can, but having to work without
things like assignment is difficult for me. The arguments for it have
been pretty good in this thread so I don't think that's something that
should change. So maybe it's laziness, maybe it's prudence...who knows.
 
J

James Kanze

Interesting. std::string being a typedef for a class template, similarly
std::vector, std::list , std::map ,set
Are all these banned?

If you consider them application level code, yes. In the places
I've worked, they've been considered part of the standard
library, and application programmers weren't allowed to modify
them.
 
J

James Kanze

Header dependencies and code coupling are very, very different things.

They're related, but yes: I should have made it clear that I was
talking about compiler dependencies, and not design coupling.
Templates *reduce* coupling.

They can be used for design decoupling, especially in lower
level software. It's not automatic, though; a poorly designed
template can also increase coupling.

The important thing to realise is that they're a tool. Like
most (or even all) tools, they have a cost. If the advantages
of using the tool outweigh the cost, then you should use it. If
they don't, then you shouldn't.
 
K

kwikius

If you consider them application level code, yes.  In the places
I've worked, they've been considered part of the standard
library, and application programmers weren't allowed to modify
them.

Theres a difference between application development and library
development. I have done both.

At the application level in quan, my physical quantities library ( and
I use quan a lot in my own applications) , only typedefs are used for
common quantities, which are provided by the library, the format is

quan::length::mm x;

quan::force_per_length::kN_per_m F1;

(I hope the intended quantities and units are obvious)

This is entirely similar to std::string, except that there are a large
number of quantities. Nevertheless no template parameters are used in
my own application code, though underneath there is a large amount of
template machinery.

From time to time I see pronouncements that templates are for experts
only, however this is FUD really as the only way to become expert is
to start from being a non expert.

regards
Andy Little
 

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,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top