Linked by Thom Holwerda on Mon 13th Aug 2007 17:57 UTC
General Development "A good programming language is far more than a simple collection of features. My ideal is to provide a set of facilities that smoothly work together to support design and programming styles of a generality beyond my imagination. Here, I briefly outline rules of thumb (guidelines, principles) that are being applied in the design of C++0x. Then, I present the state of the standards process (we are aiming for C++09) and give examples of a few of the proposals such as concepts, generalized initialization, being considered in the ISO C++ standards committee. Since there are far more proposals than could be presented in an hour, I'll take questions." Dr. Bjarne Stroustrup is the original designer and implementer of the C++ Programming Language.
Thread beginning with comment 263161
To view parent comment, click here.
To read all comments associated with this story, please click here.
RE[3]: C: Esperanto
by falemagn on Mon 13th Aug 2007 20:57 UTC in reply to "RE[2]: C: Esperanto"
falemagn
Member since:
2005-07-06

"Macros are bad."


Not necessarily. Macros provide for a way to transform text into other text, what's bad is the usage of macros that some people do.

With macros you could do this, in C++:

synchronized(object)
{
// Atomic operations here
}

Just like in java, and it would be totally legal C++, provided the macro synchronized expanded to something like this:

#define synchronized(o) for((o).Lock(); (o).isLocked(); (o).unLock())

Where o would be an object of a class exposing the Lock/isLocked/unLock methods. If a class inherited from a, say, synchronizable class implementing those methods, you would be able to do

someclass::somemethod()
{
synchronized(*this)
{
// bla bla bla
}
}


Which would be the equivalent of a synchronized method in the Java language.

"Range checking is good in all but the most performance-critical code."


You can have range checking in C++, you just need to either implement it in a class of your own or use some of the already existing classes.

"I'll add that manual memory management is usually (but not always) unnecessary.!"


You can have managed memory handling in C++ as well.

Reply Parent Score: 3

RE[4]: C: Esperanto
by butters on Mon 13th Aug 2007 22:06 in reply to "RE[3]: C: Esperanto"
butters Member since:
2005-07-08

Well, I admit, you can't decapitate a for loop with an inline function. But you also can't do this:

#define BAD_MACRO(x) if(x) cout << "Are macros bad?" << endl;

if(true) BAD_MACRO(might_be_zero);
else cout << "Macros are bad!" << endl;

Macros can change the way we think about truth.

Use inline functions in place of macros. If you need to inline something that isn't a function, you're doing something wrong. What's so bad about this?:

o.Lock();
// stuff
o.unLock();

That's the way C++ works, plus you avoid the unnecessary isLocked() call. Should C++ have multithreading primitives? Probably, but that's another issue.

Yes, I know you can extend C++ in all sorts of ways. But a lot of these hacks are workarounds for missing language features. You shouldn't need a special class to have a bounds-checked array. This should be an opt-out feature.

Edited 2007-08-13 22:08

Reply Parent Score: 2

RE[5]: C: Esperanto
by TheMonoTone on Mon 13th Aug 2007 22:16 in reply to "RE[4]: C: Esperanto"
TheMonoTone Member since:
2006-01-01

The mentality of C++ is you only use what you are willing to pay for, you only pay for what you use. There is an associated cost (processing time) with the features your talking about. They are "hacks" because not everyone wants the same features so why should everyone pay for them.

Reply Parent Score: 3

RE[5]: C: Esperanto
by falemagn on Mon 13th Aug 2007 22:41 in reply to "RE[4]: C: Esperanto"
falemagn Member since:
2005-07-06

Macros can change the way we think about truth.


As already said, blame the programmer, not the tool.

What's so bad about this?:

o.Lock();
// stuff
o.unLock();


The fact that you need to invoke the unLock() method explicitely, which is prone to error and is the reason for using the macro in the first place.

You shouldn't need a special class to have a bounds-checked array.


Why not?

Reply Parent Score: 1

RE[4]: C: Esperanto
by javacoder on Tue 14th Aug 2007 05:45 in reply to "RE[3]: C: Esperanto"
javacoder Member since:
2007-08-14


Just like in java, and it would be totally legal C++, provided the macro synchronized expanded to something like this:

#define synchronized(o) for((o).Lock(); (o).isLocked(); (o).unLock())


... and where would the .Lock() method come from? c++.lang.Object? (sorry, couldn't resist :-)

Reply Parent Score: 1

RE[4]: C: Esperanto
by Auxx on Tue 14th Aug 2007 06:15 in reply to "RE[3]: C: Esperanto"
Auxx Member since:
2007-04-05

Macros provide for a way to transform text into other text

Macros mean that language is not full-featured and many things can not be done with language itself. Using macros is stupid.

Reply Parent Score: 2

RE[5]: C: Esperanto
by falemagn on Tue 14th Aug 2007 06:30 in reply to "RE[4]: C: Esperanto"
falemagn Member since:
2005-07-06

"Macros mean that language is not full-featured and many things can not be done with language itself."


Macros are part of the language: your point is moot.

Edited 2007-08-14 06:30

Reply Parent Score: 2

RE[4]: C: Esperanto
by japh on Tue 14th Aug 2007 09:12 in reply to "RE[3]: C: Esperanto"
japh Member since:
2005-11-11


synchronized(object)
{
// Atomic operations here
}

Just like in java, and it would be totally legal C++, provided the macro synchronized expanded to something like this:

#define synchronized(o) for((o).Lock(); (o).isLocked(); (o).unLock())


That "synchronized" macro will only work if you have non-throwing code synchronized. Otherwise you'll end up with a lock that will stay locked forever.

In C++ you will probably want to use something like scoped locking.

You'll find an example of how that is done here:
http://en.wikipedia.org/wiki/Singleton_pattern

The MutexLocker class replaces your macro and does a better job.
In it's simplest version it looks something like this:

class MutexLocker
{
public:
MutexLocker(Mutex& pm): m(pm) { m.lock(); }
~MutexLocker() { m.unlock(); }
private:
Mutex& m;
};

In C++ there are actually very few times I feel the need to use macros. Macros create more problems than they fix in my opinion.

Reply Parent Score: 1

RE[5]: C: Esperanto
by sanders on Tue 14th Aug 2007 09:51 in reply to "RE[4]: C: Esperanto"
sanders Member since:
2005-08-09

The MutexLocker class replaces your macro and does a better job.

Of course, you can use such an AutoLock in the macro, if you insist on having a "lock" keyword. See here: http://www.stoks.nl/rants/lock.html

Edited 2007-08-14 09:51

Reply Parent Score: 1

RE[5]: C: Esperanto
by falemagn on Tue 14th Aug 2007 19:55 in reply to "RE[4]: C: Esperanto"
falemagn Member since:
2005-07-06

"

That "synchronized" macro will only work if you have non-throwing code synchronized.
"

That's true, of course. It was just an example meant to show the flexibility of the preprocessor and its possible uses, thought up in 5 seconds.

To have better examples as of why the preprocessor is useful, just have a look at the BOOST preprocessor library.

Reply Parent Score: 1

And this is WHY I RAN from C++
by christianhgross on Tue 14th Aug 2007 09:33 in reply to "RE[3]: C: Esperanto"
christianhgross Member since:
2005-11-15

It is amazing you a synchronize keyword, which is a REALLY simply concept in say Java, or C# and created a discussion.

Now imagine writing application code. The C# and Java person can focus on actually getting the problem done. Whereas the C++ developer will be arguing with another C++ on how to write a bleeden lock statement.

Yeah I am SOOOOO glad I ran from C++...

Edited 2007-08-14 09:37

Reply Parent Score: 2

japh Member since:
2005-11-11

While I didn't run from C++, I'm glad I have the option to chose different languages when I want to.

In C++ you sometimes have the illusion of success, just because you solved a problem that you have only because you use C++. It might feel good, but you haven't really accomplished much.

Reply Parent Score: 2

RE[4]: C: Esperanto
by rayiner on Tue 14th Aug 2007 21:38 in reply to "RE[3]: C: Esperanto"
rayiner Member since:
2005-07-06

You can have range checking in C++, you just need to either implement it in a class of your own or use some of the already existing classes.

Range-checking (memory safety in general) is useless as an added feature. It's something that really needs to be in the guts of the system, used by not just your code, but everything under your code.

The cost of validity-checking is zero compared to good (defensively programmed) C++ code, which does it manually anyway. It's small even compared to bad code that blindly assumes it is passed correct parameters.

Anatomy of a check (in a magnitude-squared example):


double mag_squared(vector vec) {
double sum = 0.0;
double t0, t1;
for(int i = 0; i less_than vec.length; ++i) {
if(i greater_equal vec.length()) throw_error();
t0 = vec[i];
if(i greater_equal vec.length()) throw_error();
t1 = vec[i];
sum += (t0 * t1);
}

return sum;
}


This is the canonical, naively-inserted check, in pretty much the worst case (tight loop). It looks pretty bad, doubling the code inside the loop. This canonical description also shows all the reasons why checks are actually really cheap.

1) Range analysis can easily show that the induction variable (i) can never be greater than the length of the vector, making the checks completely unnecessary.

2) Redundency analysis can easily show that the second check is made redundent by the first check. This is obvious in this particular case, but happens in code where valies are reused. Type checks in particular, are easily removed by redundency analysis.

3) Even if you can't get rid of the checks, it's not so bad. It's easy to prove that the length of the vector doesn't change, so it can be loaded into a register outside the loop. Inside the loop, the checks are a simple compare and and perfectly-predictable conditional jump. On a modern load/store-limited CPU, there are almost always idle integer units available to execute these ops, and as a result they're almost free.

You can have managed memory handling in C++ as well.

See above rant on range-checking.

Edited 2007-08-14 21:47

Reply Parent Score: 2

RE[5]: C: Esperanto
by ashigabou on Wed 15th Aug 2007 04:45 in reply to "RE[4]: C: Esperanto"
ashigabou Member since:
2005-11-11

The thing funny with range checking is that its cost is, at least for numerical code, much lower than the ones caused by aliasing. I am often baffled by people who think that C or C++ has not cost at all for performance critical code. Generally, I feel like C++ encourage premature optimization (the virtual keyword, for example), for no reason at all.

Reply Parent Score: 1

RE[5]: C: Esperanto
by falemagn on Wed 15th Aug 2007 11:00 in reply to "RE[4]: C: Esperanto"
falemagn Member since:
2005-07-06

rayiner,

your example in C++ would be best implemented with an iterator or with the foreach macro described earlier. All your example proves is that when there's no link between syntax and semantics the compiler cannot optimize unnecessary code away, therefore the solution is to create that link, which is what an interator pattern does.

Reply Parent Score: 1