473,386 Members | 1,647 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

Effeciency

I want to have an unsigned integer-like thing, that for now only allows
the bitwise operators. I have defined these operators and their
self-assigning cousins.

This works, but I would like to know what the most effecient way of
doing this is. Preferably, there should be no overhead compared to a
read unsigned long int. No extra temporaries, full inlining etc. The
same code should be generated.

The only difference between an unsigned long int and my class should be
that it is it's own separate type and that I control what operations and
conversions are possible/automatic.

class MyClass
{
public:
MyClass() {}
explicit MyClass(unsigned long int uli)
{
bb = uli;
}

MyClass& operator &=(const MyClass& rhs) { bb &= rhs.bb; return
*this; }
MyClass& operator |=(const MyClass& rhs) { bb |= rhs.bb; return
*this; }
MyClass& operator ^=(const MyClass& rhs) { bb ^= rhs.bb; return
*this; }

MyClass operator &(const MyClass& rhs) { return MyClass(bb & rhs.bb); }
MyClass operator |(const MyClass& rhs) { return MyClass(bb | rhs.bb); }
MyClass operator ^(const MyClass& rhs) { return MyClass(bb ^ rhs.bb); }

private:
unsigned long int bb;
};

/David
Jul 22 '05 #1
41 1693
On Mon, 26 Jan 2004 02:33:22 +0100, David Rasmussen <da*************@gmx.net> wrote:
I want to have an unsigned integer-like thing, that for now only allows
the bitwise operators. I have defined these operators and their
self-assigning cousins.

This works, but I would like to know what the most effecient way of
doing this is. Preferably, there should be no overhead compared to a
read unsigned long int. No extra temporaries, full inlining etc. The
same code should be generated.

The only difference between an unsigned long int and my class should be
that it is it's own separate type and that I control what operations and
conversions are possible/automatic.


That is a quality-of-implementation issue.

C++ formally allows the compiler to generate any amount of overhead.

If you can live with somewhat less control over operations it might be
an idea to consider an enum-type as your type (just a thought).

Jul 22 '05 #2
David Rasmussen wrote:
I want to have an unsigned integer-like thing, that for now only allows
the bitwise operators. I have defined these operators and their
self-assigning cousins.

This works, but I would like to know what the most effecient way of
doing this is. Preferably, there should be no overhead compared to a
read unsigned long int. No extra temporaries, full inlining etc. The
same code should be generated.

The only difference between an unsigned long int and my class should be
that it is it's own separate type and that I control what operations and
conversions are possible/automatic.

class MyClass
{
public:
MyClass() {}
explicit MyClass(unsigned long int uli)
{
bb = uli;
}
.... knit - best to get into the habbit of using initializer lists
i.e.:
explicit MyClass(unsigned long int uli)
: bb(uli)
{
}

You lack a copy constructor:

MyClass( const MyClass & );

.... and a default constructor

MyClass();

.... an an assignment operator.

MyClass& operator= (const MyClass& rhs);

It's hard to do much without the above functions.

As far as performance goes - the operators below seem fine.

MyClass& operator &=(const MyClass& rhs) { bb &= rhs.bb; return
*this; }
MyClass& operator |=(const MyClass& rhs) { bb |= rhs.bb; return
*this; }
MyClass& operator ^=(const MyClass& rhs) { bb ^= rhs.bb; return
*this; }

This looks about as good as you could as well. The only picky issue is
that you're duplicating the functionality above but you're likely not
going to get any issues here because of that.
MyClass operator &(const MyClass& rhs) { return MyClass(bb & rhs.bb); }
MyClass operator |(const MyClass& rhs) { return MyClass(bb | rhs.bb); }
MyClass operator ^(const MyClass& rhs) { return MyClass(bb ^ rhs.bb); }

private:
unsigned long int bb;
};



Jul 22 '05 #3
Alf P. Steinbach wrote:

That is a quality-of-implementation issue.

I know, but...
C++ formally allows the compiler to generate any amount of overhead.

I know, but...

Maybe I should rephrase it: I want to make sure that I don't make it
unnecesarily inefficient. I want to give the compiler the best working
conditions.
If you can live with somewhat less control over operations it might be
an idea to consider an enum-type as your type (just a thought).


I can't, but thanks for the suggestion :)

/David
Jul 22 '05 #4

"Gianni Mariani" <gi*******@mariani.ws> wrote in message news:bv********@dispatch.concentric.net...
]>
You lack a copy constructor:

MyClass( const MyClass & );

... and a default constructor

MyClass();

... an an assignment operator.

MyClass& operator= (const MyClass& rhs);

It's hard to do much without the above functions.


The compiler generates the copy-assignment operator and the
copy constructor for him. As lame as his class is, the compiler
generated ones are just fine.

However, the presence of the constructor from unsinged int means
the default constructor is supressed. He probably wants that one.
Jul 22 '05 #5
Ron Natalie wrote:

The compiler generates the copy-assignment operator and the
copy constructor for him. As lame as his class is, the compiler
generated ones are just fine.

My class is lame?

What I am trying to achieve here is something sorely lacking in C++, but
available in other languages, e.g. Ada.

What I really want, is just for the compiler to do some more work, to
distinguish between my class and an int. That is, more typesafety. This
is a compile time thing only. The compiler ensures that for example
operator + isn't used on my class. When the program is ready for
release, all MyClass instances could be replaced with just variables of
the type of the encapsulated integer. This could be done easily with a
typedef.

The effect is that I ensure type safety, and I get the effeciency of the
integer in release builds. But ideally, there shouldn't be any
performance difference between the two. This class is what the language
forces me to do in order to get some very basic type safety done by the
compiler.
However, the presence of the constructor from unsinged int means
the default constructor is supressed. He probably wants that one.


The empty default constructor? Yes.

/David
Jul 22 '05 #6

"David Rasmussen" <da*************@gmx.net> wrote in message news:bv**********@news.net.uni-c.dk...
My class is lame?
Sorry, I only meant it doesn't do much other than wrap an int. It doesn't manage pointers
or a bunch of other things that would require specialize copy semantics. Perhaps I should
have said "simple" rather than "lame."
What I am trying to achieve here is something sorely lacking in C++, but
available in other languages, e.g. Ada.
C++ isn't Ada. You can spend your time trying to make it so, but you're not
going to be happy in the long run. I'll give you the bad news now. There is no
way your class is going to be as fast as the built-in. Further, it's going to be next
to impossible to make it behave like the standard int.

What I really want, is just for the compiler to do some more work, to
distinguish between my class and an int. That is, more typesafety. This
is a compile time thing only.


You've lost me as to how not having operator+ makes things more typesafe.

Jul 22 '05 #7

"David Rasmussen" <da*************@gmx.net> wrote in message
news:bv**********@news.net.uni-c.dk...
Ron Natalie wrote:

The compiler generates the copy-assignment operator and the
copy constructor for him. As lame as his class is, the compiler
generated ones are just fine.


My class is lame?

What I am trying to achieve here is something sorely lacking in C++, but
available in other languages, e.g. Ada.

What I really want, is just for the compiler to do some more work, to
distinguish between my class and an int. That is, more typesafety. This
is a compile time thing only. The compiler ensures that for example
operator + isn't used on my class. When the program is ready for
release, all MyClass instances could be replaced with just variables of
the type of the encapsulated integer. This could be done easily with a
typedef.

The effect is that I ensure type safety, and I get the effeciency of the
integer in release builds. But ideally, there shouldn't be any
performance difference between the two. This class is what the language
forces me to do in order to get some very basic type safety done by the
compiler.
However, the presence of the constructor from unsinged int means
the default constructor is supressed. He probably wants that one.


The empty default constructor? Yes.

/David


Hi,
If I understand what you are saying...you want to typify integral types at
compile time to enforce more type safety. Then, you want to replace that
check with an actual integral type (via a typedef) for your release mode
(max efficiency).
If that is what you want, then look at the code below (sloppy - but gets
the point across):
#include <iostream>

template <typename Underlying, int MixType>
struct MyClass {
explicit MyClass(Underlying val) : myVal(val) { /* */ };
friend MyClass operator*(const MyClass& m1, const MyClass& m2) {
return(static_cast<MyClass>(m1.myVal * m2.myVal)); }
friend MyClass operator+(const MyClass& m1, const MyClass& m2) {
return(static_cast<MyClass>(m1.myVal + m2.myVal)); }
// etc.

friend std::ostream& operator<<(std::ostream& os, const MyClass& m) { os
<< m.myVal; return(os); }

private:
Underlying myVal;
};

// Make as many types you want here
typedef MyClass<unsigned long, 1> FirstIntType;
typedef MyClass<unsigned long, 2> SecondIntType;

// Later replace for maximum efficiency
// typedef unsigned long FirstIntType;
// typedef unsigned long SecondIntType;

int main()
{
FirstIntType a(1), b(2);
SecondIntType c(4), d(5);
std::cout << a * b << std::endl; // ok
std::cout << c * d << std::endl; // ok
std::cout << a * c << std::endl; // error ==> can't mix
std::cout << a * 4 << std::endl; // error ==> can't mix
return(0);
}

Good Luck,
Shane
Jul 22 '05 #8
Ron Natalie wrote:

Sorry, I only meant it doesn't do much other than wrap an int. It doesn't manage pointers
or a bunch of other things that would require specialize copy semantics. Perhaps I should
have said "simple" rather than "lame."

Okay :)
What I am trying to achieve here is something sorely lacking in C++, but
available in other languages, e.g. Ada.

C++ isn't Ada.


Sure it isn't, but this is a design-notion so basic that I can't believe
that it isn't supported by the language. Especially with it's "zero
overhead" principle.

The reason Ariane 5 crashed was because two different departments were
using ints to express the concept of length. The problem was that one
department used meters, the other used feet. In Ada, you can define a
derived type of the builint types, that is limited in some way. That is,
you can define an integer type of Feet that is a different type from the
integer type of Meters, and from all other integers. You don't have to,
but you have the choice. You will have no performance hit. The compiler
will just use normal integers (whatever they are on the platform in
question), but at compile-time, the compiler will ensure that you never
assign length in feet to length in meters.

This notion is very basic and comes up in all sorts of designs. We're
just asking the compiler to do some very reasonable type checking.

We can't do this directly in C++ unfortunately. The only way to get a
new type, is to make a class (or an enum, but that is a crippled type
that we have almost no control over). That means, as you say, overhead.
Goodbye zero overhead principle.

You can spend your time trying to make it so, but you're not
going to be happy in the long run.
I don't want C++ to be Ada. But I would like to be able to express very
basic design notions in C++, that the underlying hardware can express
directly and naturally.
I'll give you the bad news now. There is no
way your class is going to be as fast as the built-in. Further, it's going to be next
to impossible to make it behave like the standard int.

Impossible? Why?
What I really want, is just for the compiler to do some more work, to
distinguish between my class and an int. That is, more typesafety. This
is a compile time thing only.

You've lost me as to how not having operator+ makes things more typesafe.


I haven't said that. Not having operator+ is something unrelated that
has to do with the type I want. I simply don't need operator+ for my
type. It has nothing to do with type safety.

What _does_ have something to do with type safety is, like the
Feet/Meter example above, that my class although integer-like, could
never be confused with a normal integer. That is a very reasonable
design criteria, and a source of real bugs in my experience. And it
could be so simple to eliminate.

The simplest way to do it would be a new keyword that allowed one to
define a new strong type based on an old one, whether builtin or not. Like:

newtype unsigned long int MyClass;

That's it. Problem solved.

/David
Jul 22 '05 #9
VANNA CHHUM wrote:


Hi,
If I understand what you are saying...you want to typify integral types at
compile time to enforce more type safety. Then, you want to replace that
check with an actual integral type (via a typedef) for your release mode
(max efficiency).
If that is what you want, then look at the code below (sloppy - but gets
the point across):


That is very much along the lines of what I wanted! You understand :)

My only problem is that I also want to be able to overload functions
based on my new type, for example the << operator with output streams (I
don't want to have number printed for my type, I want something
different). That works as long as I am using your code or my own. But as
soon as I switch to the builtin long int, I get errors because C++ can't
overload on just typedefs.

But thanks for your suggestion, I will give it a think.

/David
Jul 22 '05 #10
David Rasmussen wrote:
[SNIP]
The reason Ariane 5 crashed was because two different departments were
using ints to express the concept of length. The problem was that one
department used meters, the other used feet.
IIRC this is not true. Ariane was the crashed rocket, wasn't it? And that
has crashed because some program was not stopped after it was not in use
anymore, and sent out bad data. The thing which has crashed for the reason
you say was a Mars thing. Was it called Polar Lander?
In Ada, you can define a
derived type of the builint types, that is limited in some way.

[SNIP]

You will need to read Design and Evolution of C++, and you will get answers
to all of your doubts. There are reasons why you cannot inherit from int in
C++.

--
Attila aka WW
Jul 22 '05 #11
Attila Feher wrote:

IIRC this is not true. Ariane was the crashed rocket, wasn't it? And that
has crashed because some program was not stopped after it was not in use
anymore, and sent out bad data. The thing which has crashed for the reason
you say was a Mars thing. Was it called Polar Lander?

Maybe you're right, but the point still stands.
In Ada, you can define a
derived type of the builint types, that is limited in some way.


[SNIP]

You will need to read Design and Evolution of C++, and you will get answers
to all of your doubts. There are reasons why you cannot inherit from int in
C++.


I own that book and have read it. Very interesting read indeed. In some
cases, Bjarne expresses doubt as whether some design decision was the
right one, and where I agree with this doubt. In other cases he makes a
weak defense for not including some very good idea. And some issues he
doesn't adress at all. Most issues he addresses, and in a convincing manner.

I don't think you can find anything in that book about why you can't
have the compiler to that added type checking on types derived from
builtin types. I also doubt very much that you can come up with any good
reasons for leaving it out.

/David
Jul 22 '05 #12
David Rasmussen wrote:
VANNA CHHUM wrote:


Hi,
If I understand what you are saying...you want to typify integral
types at
compile time to enforce more type safety. Then, you want to replace that
check with an actual integral type (via a typedef) for your release mode
(max efficiency).
If that is what you want, then look at the code below (sloppy - but
gets
the point across):


That is very much along the lines of what I wanted! You understand :)

My only problem is that I also want to be able to overload functions
based on my new type, for example the << operator with output streams (I
don't want to have number printed for my type, I want something
different). That works as long as I am using your code or my own. But as
soon as I switch to the builtin long int, I get errors because C++ can't
overload on just typedefs.


I believe you want strong typedef's. They're being considered for a
future version of the language.

Jul 22 '05 #13
Jeff Schwab wrote:

I believe you want strong typedef's. They're being considered for a
future version of the language.


That's certainly one of the things i want. It would solve a lot problems.

Do have any links to anything describing this consideration?

/David
Jul 22 '05 #14
David Rasmussen wrote:
[SNIP]

You will need to read Design and Evolution of C++, and you will get
answers to all of your doubts. There are reasons why you cannot
inherit from int in C++.

I own that book and have read it. Very interesting read indeed. In
some cases, Bjarne expresses doubt as whether some design decision
was the right one, and where I agree with this doubt.


I do not recall very strong doubts from that book.
In other cases he makes
a weak defense for not including some very good idea.
"weak defense" I guess you do not need to work anymore on self-confidence,
you can start on modesty and rhetorics. For example if you criticise things
it makes a lot of sense to give at least examples.
And some issues he doesn't adress at all.
So why don't you? With real arguments - of course.
Most issues he addresses, and in a
convincing manner.
Phew. This is reassuring.
I don't think you can find anything in that book about why you can't
have the compiler to that added type checking on types derived from
builtin types.
As I have asked you to find it, I find it interesting how it turned to be my
job anyways. What I can tell you is that I was able to find convincing
arguments of why Bjarne Stroustrup decided on not allowing inheritance from
fundmental types at all. Therefore I find it no surprise that he did not
waste the trees (the paper) to describe why some sort of other things are
not allowed on those types.
I also doubt very much that you can come up with any
good reasons for leaving it out.


I do not need to. At the time todays C++ has been created Bjarne Stroustrup
came up with them. OTOH if you feel that you can come up with a feasible
proposal on how to add those things into the language, and you come up with
use cases supporting the need, and you come up with convincing arguments of
why to do it the way you want it and you make an offical proposal out of it
which *convinces* *me*, I will be more than happy to present it for a straw
vote to the Evolution Working Group in Sydney this spring. But whatever you
propose has to stand the critical eyes of compiler implementers as well as
the finest minds of the industry (I am not talking about me). So be careful
to make it very convincing and possible to implement.

As for the issue itself. My feeling is that it is possible to come up with
a library based solution, which can be feasible on any quality
implementation. So based on that I find it hard to believe that anyone can
justify a core language change - but unlike you, my mind is not closed by a
prejudical decision. Show what you have got, where and how would you change
the language/the standard, what would it effect and why, what use cases
makes it possible etc. I am sure it is not only me, who will be ready to
look at it.

--
Attila aka WW
Jul 22 '05 #15
Jeff Schwab wrote:
I believe you want strong typedef's. They're being considered for a
future version of the language.


IIRC they are definitely not.

--
Attila aka WW
Jul 22 '05 #16
David Rasmussen wrote:
Jeff Schwab wrote:

I believe you want strong typedef's. They're being considered for a
future version of the language.


That's certainly one of the things i want. It would solve a lot problems.

Do have any links to anything describing this consideration?

/David

Sorry, I don't know of any off the top of my head. It's a staple issue
in comp.std.c++, though.

Jul 22 '05 #17
David,

"David Rasmussen" <da*************@gmx.net> wrote in message
news:bv**********@news.net.uni-c.dk...
I want to have an unsigned integer-like thing, that for now only allows
the bitwise operators. I have defined these operators and their
self-assigning cousins.
How about:

typedef std::bitset<32> MyClass;

Jeff F
This works, but I would like to know what the most effecient way of
doing this is. Preferably, there should be no overhead compared to a
read unsigned long int. No extra temporaries, full inlining etc. The
same code should be generated.

The only difference between an unsigned long int and my class should be
that it is it's own separate type and that I control what operations and
conversions are possible/automatic.

class MyClass
{
public:
MyClass() {}
explicit MyClass(unsigned long int uli)
{
bb = uli;
}

MyClass& operator &=(const MyClass& rhs) { bb &= rhs.bb; return
*this; }
MyClass& operator |=(const MyClass& rhs) { bb |= rhs.bb; return
*this; }
MyClass& operator ^=(const MyClass& rhs) { bb ^= rhs.bb; return
*this; }

MyClass operator &(const MyClass& rhs) { return MyClass(bb & rhs.bb); } MyClass operator |(const MyClass& rhs) { return MyClass(bb | rhs.bb); } MyClass operator ^(const MyClass& rhs) { return MyClass(bb ^ rhs.bb); }
private:
unsigned long int bb;
};

/David

Jul 22 '05 #18
Attila Feher wrote:
Jeff Schwab wrote:
I believe you want strong typedef's. They're being considered for a
future version of the language.

IIRC they are definitely not.

--
Attila aka WW


Aha... Well, never mind then. :)
Do you know where I can get more info? (I'm not a big fan of language
extensions in general, so I'm not cyring too hard about this.) I just
tried STW, though, and couldn't find anything relevant.

Jul 22 '05 #19

"Jeff Flinn" <NO****@nowhere.com> wrote in message
news:bv**********@bluegill.adi.com...
David,

"David Rasmussen" <da*************@gmx.net> wrote in message
news:bv**********@news.net.uni-c.dk...
I want to have an unsigned integer-like thing, that for now only allows
the bitwise operators. I have defined these operators and their
self-assigning cousins.
How about:

typedef std::bitset<32> MyClass;


Oops missed the 'unsigned long int' below, then this should be

typedef std::bitset<64> MyClass;
Jeff F
This works, but I would like to know what the most effecient way of
doing this is. Preferably, there should be no overhead compared to a
read unsigned long int. No extra temporaries, full inlining etc. The
same code should be generated.

The only difference between an unsigned long int and my class should be
that it is it's own separate type and that I control what operations and
conversions are possible/automatic.

class MyClass
{
public:
MyClass() {}
explicit MyClass(unsigned long int uli)
{
bb = uli;
}

MyClass& operator &=(const MyClass& rhs) { bb &= rhs.bb; return
*this; }
MyClass& operator |=(const MyClass& rhs) { bb |= rhs.bb; return
*this; }
MyClass& operator ^=(const MyClass& rhs) { bb ^= rhs.bb; return
*this; }

MyClass operator &(const MyClass& rhs) { return MyClass(bb &

rhs.bb); }
MyClass operator |(const MyClass& rhs) { return MyClass(bb |

rhs.bb); }
MyClass operator ^(const MyClass& rhs) { return MyClass(bb ^

rhs.bb); }

private:
unsigned long int bb;
};

/David


Jul 22 '05 #20
Jeff Flinn wrote:

How about:

typedef std::bitset<32> MyClass;


That wouldn't be as effecient as an int, would it?

Oops missed the 'unsigned long int' below, then this should be

typedef std::bitset<64> MyClass;


unsigned long int is at least 32 bits according to the standard, not at
least 64 bit. Sadly, there is no standard way to get a 64-bit integer.

/David
Jul 22 '05 #21

"David Rasmussen" <da*************@gmx.net> wrote in message
news:bv**********@news.net.uni-c.dk...
Jeff Flinn wrote:

How about:

typedef std::bitset<32> MyClass;


That wouldn't be as effecient as an int, would it?


That would depend on the implementation. By I would guess that 32 bits being
the most common usage, that there would be little difference. VC7.1 bitset
uses unsigned long as it's base storage type.

Oops missed the 'unsigned long int' below, then this should be

typedef std::bitset<64> MyClass;


unsigned long int is at least 32 bits according to the standard, not at
least 64 bit. Sadly, there is no standard way to get a 64-bit integer.


Sorry I confused 'long int' with 'long long'. This is the first time I've
come across 'long int' syntax. I usually see either long or int, both of
which on the majority of todays desktop systems are 32 bits.

Jeff
Jul 22 '05 #22

"David Rasmussen" <da*************@gmx.net> wrote in message news:bv**********@news.net.uni-c.dk...
The reason Ariane 5 crashed was because two different departments were
using ints to express the concept of length.


I understand your point, but the above is wrong. The famous Ariane crash
happened because of a overflowing conversion from 64 bit float to 16 bit
integer caused a software exception.

Jul 22 '05 #23
Ron Natalie wrote:

I understand your point, but the above is wrong. The famous Ariane crash
happened because of a overflowing conversion from 64 bit float to 16 bit
integer caused a software exception.


Okay :) But the point still stands.

/David
Jul 22 '05 #24
David Rasmussen <da*************@gmx.net> wrote in message news:<bv**********@news.net.uni-c.dk>...
I want to have an unsigned integer-like thing, that for now only allows
the bitwise operators. I have defined these operators and their
self-assigning cousins.
I've done this from time to time. To reduce the amount of boilerplate
code you have to write, a class template can be helpful (see below).
This works, but I would like to know what the most effecient way of
doing this is. Preferably, there should be no overhead compared to a
read unsigned long int. No extra temporaries, full inlining etc. The
same code should be generated.


There is a term for this: abstraction penalty. That is, using a UDT
instead of a built-in type adds an abstraction (plus associated error
checking), and the question is: what performance penalty (if any) do
I pay for this abstraction.

The best advice I can give is try it and see. Make sure you compile
both versions with optimizations and then compare assembly listings
and/or time both versions.

Ideally, the performance penalty should be nil, but this may not be
true in practice. Compilers are getting better and better at this
though.

Now, as to that class template... one approach is to define a very
minimal class as follows:

template<class Representation, int TypeID>
class NewType {
Representation rep;
public:
explicit NewType(Representation const& val) : rep(val)
{}

Representation const& Value() const
{
return rep;
}
};

The second template parameter's only purpose is to enable one to
define distinct types with the same underlying representation.
For example, the following typedefs name three distinct types:

typedef NewType<double, __LINE__> Meters;
typedef NewType<double, __LINE__> Seconds;
typedef NewType<double, __LINE__> MetersPerSecond;

Of course, the above class has very minimal functionality, but
there's just enough to allow you to implement operators, etc.,
as free functions, thus:

inline Seconds operator*(Seconds lhs, double rhs)
{
return Seconds(lhs.Value() * rhs);
}

inline Meters operator*(Seconds lhs, MetersPerSecond rhs)
{
return Meters(lhs.Value() * rhs.Value());
}

Using these operators we can easily demonstrate that Meters,
Seconds, and MetersPerSecond really are distinct types.

void test(Seconds time, MetersPerSecond speed)
{
Meters distance = time * speed;
Seconds s = time * speed; // error
}
Jul 22 '05 #25
> Do you know where I can get more info? (I'm not a big fan of language
extensions in general, so I'm not cyring too hard about this.) I just
tried STW, though, and couldn't find anything relevant.


I posted a question about strong typedefs (though I didn't know that
term, I made up a name called typecpy) and Jonathan Turkanis gave me
this link :

http://anubis.dkuug.dk/jtc1/sc22/wg2...2002/n1395.txt

Also check comp.std.c++
Jul 22 '05 #26
Niklas Borson wrote:
There is a term for this: abstraction penalty.
This mythical "abstraction penalty" is as illusive as Bigfoot.
That is, using a UDT instead of a built-in type adds an abstraction
(plus associated error checking), and the question is,
"What performance penalty (if any) do I pay for this abstraction?"


Please show us an example
where abstraction exacts a performance penalty.

Every alleged case of an "abstraction penalty" that I have seen so far
actually turns out to bad design and/or poor implementation.
I'd just like to see *one* case
where a penalty for abstraction is unavoidable so that I could believe.

Jul 22 '05 #27
Keith H Duggar wrote:
Do you know where I can get more info? (I'm not a big fan of language
extensions in general, so I'm not cyring too hard about this.) I just
tried STW, though, and couldn't find anything relevant.

I posted a question about strong typedefs (though I didn't know that
term, I made up a name called typecpy) and Jonathan Turkanis gave me
this link :

http://anubis.dkuug.dk/jtc1/sc22/wg2...2002/n1395.txt

Also check comp.std.c++


Thanks. Lots of good stuff in that paper.

Jul 22 '05 #28
Jeff Schwab wrote:
Attila Feher wrote:
Jeff Schwab wrote:
I believe you want strong typedef's. They're being considered for a
future version of the language.

IIRC they are definitely not.

--
Attila aka WW


Aha... Well, never mind then. :)
Do you know where I can get more info? (I'm not a big fan of language
extensions in general, so I'm not cyring too hard about this.) I just
tried STW, though, and couldn't find anything relevant.


If you look at discussions about this topic (there were both in comp.std.c++
and comp.lang.c++.moderated) you will see that names (sitting in teh
committee) always wipe strong typedefs off the table. The reason is that
there is no real use case for it, except maybe in a RAD kinda development.

If you look at Lois'es paper, you can see that the strong typedefs are lies.
Day is not an int. Month is not an int. And so forth. You can assing
34987590 to an int, but neither day, nor month can ever be that big.

So while under rapid development it might be beneficial to fast make
day/month etc. types without actually implementing them first, IMHO it would
only bring errors into the code, since you may forget that "lieing" type
there...

What I rather would like to see is user defined literal. So that I could
say 12day (of course this is not a proposed syntax, only an example) and the
system could check compile time if it _can_ be a day. And this leads to run
code of the sources being compiled, compile time... Also "adding new
syntax" to the language. So it is an area to be approach very carefully.

--
Attila aka WW
Jul 22 '05 #29
"E. Robert Tisdale" <E.**************@jpl.nasa.gov> wrote in message news:<40**************@jpl.nasa.gov>...
Niklas Borson wrote:
There is a term for this: abstraction penalty.
This mythical "abstraction penalty" is as illusive as Bigfoot.
That is, using a UDT instead of a built-in type adds an abstraction
(plus associated error checking), and the question is,
"What performance penalty (if any) do I pay for this abstraction?"


Please show us an example
where abstraction exacts a performance penalty.


See above where I said "(if any)". I never made any claims about
the value of the abstraction penalty, only that the term exists and
that it's a useful benchmark.

Google for "abstraction penalty" "stepanov benchmark" and you should
find some useful information. I believe this benchmark yields values
close to 1 for some (but not all) modern C++ compilers.
Every alleged case of an "abstraction penalty" that I have seen so far
actually turns out to bad design and/or poor implementation.
I'd just like to see *one* case
where a penalty for abstraction is unavoidable so that I could believe.


I agree with you that one should not avoid useful abstractions because of
ill-conceived assumptions about their performance. (In fact, one of the
motivations of the Stepanov benchmark was to debunk such assumptions.)

Just for fun, consider the following three nearly-identical functions.
All three multiply two doubles and return the product; the difference
is in whether some or all of the doubles are encapsulated by UDTs
(The UDTs and operator* are defined in my previous post):

double test1(double time, double speed)
{
return time * speed;
}

double test2(Seconds time, MetersPerSecond speed)
{
return (time * speed).Value();
}

Meters test3(Seconds time, MetersPerSecond speed)
{
return time * speed;
}

One possible "abstraction penalty" benchmark would be to compare
the timings of these three functions. I haven't done so, but I did
compare the assembly listings generated by MSVC7.1 at -O2. I found
that the first two functions generate identical code. The third is
slightly different because the return mechanism for UDTs differs
from that for doubles. (The double is left on the floating point
stack; the UDT is stored in a caller-specified memory address.)

Based on the above, I would expect negligable or no performance
difference between code that used the built-in double type and
code that used the more strongly-typed wrapper classes. That,
however, is a useful thing to know which is why it's useful to
have abstraction penalty benchmarks.
Jul 22 '05 #30
"E. Robert Tisdale" <E.**************@jpl.nasa.gov> wrote in message news:<40**************@jpl.nasa.gov>...
Niklas Borson wrote:
[snip]

Based on the above, I would expect negligable or no performance
difference between code that used the built-in double type and
code that used the more strongly-typed wrapper classes.
That, however, is a useful thing to know which is why
it's useful to have abstraction penalty benchmarks.
I think that you would find that the "abstraction penalty"
would disappear in the examples above
if you would just inline these functions.


Sure, provided the functions were actually inlined which should
be the case for trivial functions like these.

For non-inlined functions, it appears that UDTs cannot be returned
using exactly the same mechanism as native types (on this particular
implementation). However, in all other respects, the compiler
generates exactly the same code for the "more abstract" UDT as it
does for the native type.

It seems to me that where I said "negligable or no performance
difference" above covers these two cases pretty well.

I'm struggling to figure out where we disagree here.
C++ languages designers and compiler developers
have gone to great pains to ensure that
there is no inherent abstraction penalty.


True, but this is an area where (1) all compilers are not equal,
(2) a lot of progress has happened quite recently, and (3) the
existence of an "abstraction penalty" benchmark may well have
helped along some of the progress in this area.
Jul 22 '05 #31
Attila Feher wrote:

If you look at discussions about this topic (there were both in comp.std.c++
and comp.lang.c++.moderated) you will see that names (sitting in teh
committee) always wipe strong typedefs off the table. The reason is that
there is no real use case for it, except maybe in a RAD kinda development.

The real use cases are everywhere. I know of almost no code that
coulnd't benefit from this. It is a very very basic design notion.
If you look at Lois'es paper, you can see that the strong typedefs are lies.
Day is not an int. Month is not an int. And so forth. You can assing
34987590 to an int, but neither day, nor month can ever be that big.

But you can't assign 34987590 to a Day. So all is fine.
So while under rapid development it might be beneficial to fast make
day/month etc. types without actually implementing them first, IMHO it would
only bring errors into the code, since you may forget that "lieing" type
there...

How? Why? What do you mean? Do you know the languages that have this,
and how natural and beneficial it is there?
What I rather would like to see is user defined literal. So that I could
say 12day (of course this is not a proposed syntax, only an example) and the
system could check compile time if it _can_ be a day. And this leads to run
code of the sources being compiled, compile time... Also "adding new
syntax" to the language. So it is an area to be approach very carefully.


I don't quite understand your proposal.

/David
Jul 22 '05 #32
Niklas Borson wrote:

There is a term for this: abstraction penalty. That is, using a UDT
instead of a built-in type adds an abstraction (plus associated error
checking), and the question is: what performance penalty (if any) do
I pay for this abstraction.

Sure, but my point is that sometimes we want something with the same
semantics and the same operations as a built-in type (which usually have
great direct hardware support). So why should the language force you to
have non-zero overhead, when it is very trivial and easy, formally, to
get zero-overhead? If I define two types that are equivalent to
'double', but one represents length in feet, the other in meters, then I
want these types to behave exactly as doubles, and there is no need for
anything but a compile time penalty. But if I want the type system to
help me enforce this very basic design notion, C++ forces my to add
(possible) runtime overhead. Bjarne Stroustrup's own analogy example of
what static typing is, in TC++PL is even about physical units. He
explains how scientists are very careful not to mix different units.
This notion appears in the base of every design. That doesn't mean that
we couldn't use all of C++'s other features on top. It just strengthens
the base and the type system.
[SNIP template]


Thanks.

/David
Jul 22 '05 #33
David Rasmussen wrote:
Attila Feher wrote:

If you look at discussions about this topic (there were both in
comp.std.c++ and comp.lang.c++.moderated) you will see that names
(sitting in teh committee) always wipe strong typedefs off the
table. The reason is that there is no real use case for it, except
maybe in a RAD kinda development.


The real use cases are everywhere. I know of almost no code that
coulnd't benefit from this. It is a very very basic design notion.


I am yet to see *one* real use case for it. You did not list one either.
If you look at Lois'es paper, you can see that the strong typedefs
are lies. Day is not an int. Month is not an int. And so forth.
You can assing 34987590 to an int, but neither day, nor month can
ever be that big.


But you can't assign 34987590 to a Day. So all is fine.


Of course you can. Day is just another name for int.
So while under rapid development it might be beneficial to fast make
day/month etc. types without actually implementing them first, IMHO
it would only bring errors into the code, since you may forget that
"lieing" type there...


How? Why? What do you mean? Do you know the languages that have this,
and how natural and beneficial it is there?


I see nothing natural and beneficial in calling an int Day and then still
allow it to behave as an int. Like how much sense Day << 12 makes? Or Day
& 0xabcd076f?
What I rather would like to see is user defined literal. So that I
could say 12day (of course this is not a proposed syntax, only an
example) and the system could check compile time if it _can_ be a
day. And this leads to run code of the sources being compiled,
compile time... Also "adding new syntax" to the language. So it is
an area to be approach very carefully.


I don't quite understand your proposal.


It is not my proposal. It is Bjarne Stroustrup's:
http://anubis.dkuug.dk/jtc1/sc22/wg2...2003/n1511.pdf

--
Attila aka WW
Jul 22 '05 #34

"Attila Feher" <at**********@lmf.ericsson.se> wrote in message
news:bv**********@newstree.wise.edt.ericsson.se...
David Rasmussen wrote:
Attila Feher wrote:
What I rather would like to see is user defined literal. So that I could say 12day (of course this is not a proposed syntax, only an
example) and the system could check compile time if it _can_ be a
day. And this leads to run code of the sources being compiled,
compile time... Also "adding new syntax" to the language. So it is an area to be approach very carefully.


I don't quite understand your proposal.


It is not my proposal. It is Bjarne Stroustrup's:
http://anubis.dkuug.dk/jtc1/sc22/wg2...2003/n1511.pdf


If I recall correctly, Stroustrup's favored treatment of user-defined
literals (which I think would be very useful) does not involve new
syntax. I think he was leaning toward using ordinary constructor
invocation notation for literals, and no special keyword for literal
constructors.

Jonathan
Jul 22 '05 #35
Jonathan Turkanis wrote:
"Attila Feher" <at**********@lmf.ericsson.se> wrote in message
news:bv**********@newstree.wise.edt.ericsson.se...
David Rasmussen wrote:
Attila Feher wrote:

What I rather would like to see is user defined literal. So that I
could say 12day (of course this is not a proposed syntax, only an
example) and the system could check compile time if it _can_ be a
day. And this leads to run code of the sources being compiled,
compile time... Also "adding new syntax" to the language. So it
is an area to be approach very carefully.
I don't quite understand your proposal.


It is not my proposal. It is Bjarne Stroustrup's:
http://anubis.dkuug.dk/jtc1/sc22/wg2...2003/n1511.pdf


If I recall correctly, Stroustrup's favored treatment of user-defined
literals (which I think would be very useful) does not involve new
syntax. I think he was leaning toward using ordinary constructor
invocation notation for literals, and no special keyword for literal
constructors.


That is why I said: "of course this is not a proposed syntax". It was only
an example.

--
Attila aka WW
Jul 22 '05 #36
Attila Feher wrote:

I am yet to see *one* real use case for it. You did not list one either.

Show me some random code from whereever, and I shall show you where
strong typedefs would only improve the correspondance between the real
world notions involved, the design, and the C++ implementation.

Look at some quality Ada, ML, Pascal etc. code (it exists in abundance).
They all use this notions at the base of the language in one form or
another.

Of course you can. Day is just another name for int.

Then you don't understand the full idea of strong typedefs. Day would be
another type altogether, and you can't assign any other type to this or
vice versa. But you of course supply explicit conversions. Closely
related to strong typedefs is the possibility of controling operations
and conversions of the type used.

The obvious way of making a string Day type would not be to make it from
an int, but from an enum. If I could say

strong_typedef enum Day {monday,tuesday,[...],sunday};

you could only assign a Day to a Day, not an int. As said above, you
should be able to control the interface of such a strong type, that is,
it's operations and conversions. So you should be able to disable
operations that doesn't make sense.

In fact, there is nothing int-like about Day from a design point of view
or from the POV of the users of Day, even if an enum is represented by
the compiler as an int. It's just that the compiler already is very
effecient at using ints (and hence enums), so we base our new type on
that mostly because we need the same semantics, and we might as well
have the ease of defining this relationship, and the effeciency that
follows. It shouldn't be hard to express basic design notions.

I see nothing natural and beneficial in calling an int Day and then still
allow it to behave as an int.
It is not allowed to behave like an int. Not if the feature is
implemented correctly.
Like how much sense Day << 12 makes? Or Day
& 0xabcd076f?

It doesn't and shouldn't be allowed. One should be able to control the
interface to ones strong type, and disable unmeaningful operations.

I really can't believe you're asking questions like this since the
notion of strong typedefs and the notion of strong enums and strong
types derived from a native type, are not new in most languages. The
benefits and properties etc. of these are well known.


It is not my proposal. It is Bjarne Stroustrup's:
http://anubis.dkuug.dk/jtc1/sc22/wg2...2003/n1511.pdf


Well, I still didn't understand it the way you wrote it, but I will read
the proposal.

/David
Jul 22 '05 #37
David Rasmussen wrote:
Attila Feher wrote:

I am yet to see *one* real use case for it. You did not list one
either.

Show me some random code from whereever, and I shall show you where
strong typedefs would only improve the correspondance between the real
world notions involved, the design, and the C++ implementation.


Why would I work on it? You are the one who wants it.
Look at some quality Ada, ML, Pascal etc. code (it exists in
abundance). They all use this notions at the base of the language in
one form or another.
We talk about C++ here, and what matters if it makes sense in C++.
Of course you can. Day is just another name for int.


Then you don't understand the full idea of strong typedefs. Day would
be another type altogether, and you can't assign any other type to
this or vice versa. But you of course supply explicit conversions.
Closely related to strong typedefs is the possibility of controling
operations and conversions of the type used.


And it would still have all the (mostly meaningless) operations what can be
done on an int.
The obvious way of making a string Day type would not be to make it
from an int, but from an enum. If I could say

strong_typedef enum Day {monday,tuesday,[...],sunday};
That is DayOfWeek...
you could only assign a Day to a Day, not an int. As said above, you
should be able to control the interface of such a strong type, that
is, it's operations and conversions. So you should be able to disable
operations that doesn't make sense.
Except that we were not talking about days of a week, but the day part of a
date.

[SNIP]
I see nothing natural and beneficial in calling an int Day and then
still allow it to behave as an int.


It is not allowed to behave like an int. Not if the feature is
implemented correctly.


So how _would_ it behave? You just gave a separate name for a type.
Like how much sense Day << 12 makes? Or Day
& 0xabcd076f?


It doesn't and shouldn't be allowed. One should be able to control the
interface to ones strong type, and disable unmeaningful operations.


So you are - in fact - creating another type, and *not* a strong typedef.
I really can't believe you're asking questions like this since the
notion of strong typedefs and the notion of strong enums and strong
types derived from a native type, are not new in most languages. The
benefits and properties etc. of these are well known.


Then name *one*. You have just proven above yourself, that you want
something else/more than strong typedef. Just to create another name for a
type is useless.

Adding more freedom to C++ to create user defined types - up to a sensible
level, keeping the zero overhead policy in mind - is a good thing to do.
Strong typedef OTOH are not.

--
Attila aka WW
Jul 22 '05 #38
Attila Feher wrote:

I do not recall very strong doubts from that book.

Then read it again. Several places Bjarne expresses that some things are
not exactly as he wishes, and may well be changed later.

"weak defense" I guess you do not need to work anymore on self-confidence,
you can start on modesty and rhetorics.
So now I am not allowed to say anything building on my own experience
and the experience of thousand others using the features in question, in
other languages, just because it disagrees with Bjarne? Get real.

I am not at all claiming to understand language design as well as Bjarne
does. But that doesn't mean that some points in his book are more well
argued than others. For example, he sometimes say something to the
effect that this or that feature isn't included since, although it can
be helpful and powerful, it can also be misused especially by beginners.
I don't think that is a valid argument against a feature. He even says
so himself, that one shouldn't underestimate the professional
programmers that uses a language.

And some issues he doesn't adress at all.
So why don't you? With real arguments - of course.


You want me to write a book? I am just stating my opinions after reading
the book (a year ago or so). If I were to write a useful and valid
criticism that anybody can use for anything, I am not going to say
something random in a newsgroup. I would read the book again and
carefully comment where I thought i was needed, and publish it somewhere
on the net. Many people would disagreee with me, and maybe many would
agree. You would have a hard time making a hard proof that one group was
right and the other was wrong. Language design is not an exact science.
But I haven't done this yet. That doesn't mean that I can't comment on
his book. Or if so, then please don't comment yourself.

Phew. This is reassuring.

You're hard to take serious now. Please take the discussion serious, or
don't say anything.

As I have asked you to find it, I find it interesting how it turned to be my
job anyways.
I don't see how it is my job. As far as I'm concerned, you're the one
making unsubstantiated statements. I understand that you probably think
the same about me. But that doesn't make it my job more than yours.
What I can tell you is that I was able to find convincing
arguments of why Bjarne Stroustrup decided on not allowing inheritance from
fundmental types at all.
That's not exactly what we're discussing. I am not necesarily talking
about "inheritance" in the traditional C++ way.
Therefore I find it no surprise that he did not
waste the trees (the paper) to describe why some sort of other things are
not allowed on those types.

Sorry, I don't understand this.

I do not need to.
Well, yes, if you want to participate in a discussion where that is your
point.
At the time todays C++ has been created Bjarne Stroustrup
came up with them.
And therefore we can't discuss the langauge?
OTOH if you feel that you can come up with a feasible
proposal on how to add those things into the language, and you come up with
use cases supporting the need, and you come up with convincing arguments of
why to do it the way you want it and you make an offical proposal out of it
which *convinces* *me*, I will be more than happy to present it for a straw
vote to the Evolution Working Group in Sydney this spring.
I don't have the time, but it is an interesting proposal. I will
consider writing a proposal whenever I get the time to do it.
But whatever you
propose has to stand the critical eyes of compiler implementers as well as
the finest minds of the industry (I am not talking about me). So be careful
to make it very convincing and possible to implement.

Of course. "Possible to implement" is the easy part. It is a feature
that is so easy to add to any C++ compiler implementation in existance,
in my experience with compiler design.
As for the issue itself. My feeling is that it is possible to come up with
a library based solution, which can be feasible on any quality
implementation.
Really? Interesting. Could you outline this?
So based on that I find it hard to believe that anyone can
justify a core language change - but unlike you, my mind is not closed by a
prejudical decision.
It seems like you are the prejudical one right now. You don't know
anything about whether my "mind is closed". I don't know whether yours
is, which is why I don't make such unsubstantiated claims, that btw. has
nothing to do with the subject at hand. Let's get back to that.
Show what you have got, where and how would you change
the language/the standard, what would it effect and why, what use cases
makes it possible etc. I am sure it is not only me, who will be ready to
look at it.


This issue is important to me so I probably will do that, when time
allows it.

/David
Jul 22 '05 #39
David Rasmussen wrote:
Attila Feher wrote:

I do not recall very strong doubts from that book.

Then read it again. Several places Bjarne expresses that some things
are not exactly as he wishes, and may well be changed later.


I see no doubt in this. The word you have been looking for is probably
light regret as opposed to strong doubt.
"weak defense" I guess you do not need to work anymore on
self-confidence, you can start on modesty and rhetorics.


So now I am not allowed to say anything building on my own experience
and the experience of thousand others using the features in question,
in other languages, just because it disagrees with Bjarne? Get real.


From the two of us I am not the one who needs it most.
I am not at all claiming to understand language design as well as
Bjarne does.
I see.
But that doesn't mean that some points in his book are
more well argued than others.
Yes? And a topic being well argued in the book has to do *what* with the
standard C++ language? (Done by a large group of people and companies.)
For example, he sometimes say something
to the effect that this or that feature isn't included since,
although it can be helpful and powerful, it can also be misused
especially by beginners. I don't think that is a valid argument
against a feature. He even says so himself, that one shouldn't
underestimate the professional programmers that uses a language.
Yes. And most of all he also says that a programing language is not a set
of ad-hoc features, thrown together into a mess. And he also says (more to
our point) that a feature should provide enough benefits to be added and
complicate the lifes of everyone involved.
And some issues he doesn't adress at all.


So why don't you? With real arguments - of course.


You want me to write a book?


No. I want you to say *one* concrete thing, instead of generic BS.
I am just stating my opinions after
reading the book (a year ago or so).
Great. Your opinion is that the book is not convincing. Mine is that it
is. Great. Now that we now opinions, how about facts?
If I were to write a useful and
valid criticism that anybody can use for anything, I am not going to
say something random in a newsgroup.
I see that you can explain why you do not say anything concrete or factual.
How about coming up with some real life arguments?
I would read the book again and
carefully comment where I thought i was needed, and publish it
somewhere on the net. Many people would disagreee with me, and maybe
many would agree.
I should be honest: I could not care less about how would you make a book
review. This is comp.lang.c++
You would have a hard time making a hard proof that
one group was right and the other was wrong.
You are mixing things. This is not about me, deciding who is wrong or
right, but you, putting down a man and a book without any arguments or
facts.
Language design is not an exact science.
Are you sure?
But I haven't done this yet. That doesn't mean that
I can't comment on his book. Or if so, then please don't comment
yourself.


Wow. Why don't you try to imagine that this is not about you or me or a
fight or p3nis envy, but about coming up with hard facts in a technical
newsgroups, where unfounded opinions of well known experts are not taken
lightly?
Phew. This is reassuring.


You're hard to take serious now. Please take the discussion serious,
or don't say anything.


I live in a free world. Respect this. BTW the above line of mine says
exactly what you said: be serious please.
As I have asked you to find it, I find it interesting how it turned
to be my job anyways.


I don't see how it is my job. As far as I'm concerned, you're the one
making unsubstantiated statements. I understand that you probably
think the same about me. But that doesn't make it my job more than
yours.


I made no unsubstantiated statements. You did. Anyways, let's THINk, even
if it is hard for you: what is possible/easy? To prove something does not
exist or that it does? Think about this.

To whom it is important to come up with proof that a feature is important?
To you, so I will vote yes on the proposal in the committee (if I get there)
or to me, who could not care less, because right now I am sure it is
useless.
What I can tell you is that I was able to find convincing
arguments of why Bjarne Stroustrup decided on not allowing
inheritance from fundmental types at all.


That's not exactly what we're discussing. I am not necesarily talking
about "inheritance" in the traditional C++ way.


Good. Then tell what you do talk about. Because as I saw you mentioned
this area.
Therefore I find it no surprise that he did not
waste the trees (the paper) to describe why some sort of other
things are not allowed on those types.


Sorry, I don't understand this.


It happens.
I do not need to.


Well, yes, if you want to participate in a discussion where that is
your point.


You have definitely missed the point! *You* want to put the feature into
the language. *You* need to come up with good points to convince me. That
is how it works.
At the time todays C++ has been created Bjarne Stroustrup
came up with them.


And therefore we can't discuss the langauge?


That is what you say. I did not say anything like it. But techincal
discussions are known to contain facts, so I was looking for those.
OTOH if you feel that you can come up with a feasible
proposal on how to add those things into the language, and you come
up with use cases supporting the need, and you come up with
convincing arguments of why to do it the way you want it and you
make an offical proposal out of it which *convinces* *me*, I will be
more than happy to present it for a straw vote to the Evolution
Working Group in Sydney this spring.


I don't have the time, but it is an interesting proposal. I will
consider writing a proposal whenever I get the time to do it.


Do it so. And if you want it to get accepted, you probably do not want to
start it with baseless (factless) criticizm.
But whatever you
propose has to stand the critical eyes of compiler implementers as
well as the finest minds of the industry (I am not talking about
me). So be careful to make it very convincing and possible to
implement.


Of course. "Possible to implement" is the easy part. It is a feature
that is so easy to add to any C++ compiler implementation in
existance, in my experience with compiler design.


Since you did not describe the feature and I do not know your experience
with compiler design, I should say that I cannot take this statement too
seriously.
As for the issue itself. My feeling is that it is possible to come
up with a library based solution, which can be feasible on any
quality implementation.


Really? Interesting. Could you outline this?


Nope. Why? As I said: I do not need it. If you do need it, you do the
work. If you have no time to do it (it is not important to you) why should
I bother?
So based on that I find it hard to believe that anyone can
justify a core language change - but unlike you, my mind is not
closed by a prejudical decision.


It seems like you are the prejudical one right now. You don't know
anything about whether my "mind is closed". I don't know whether yours
is, which is why I don't make such unsubstantiated claims, that btw.
has nothing to do with the subject at hand. Let's get back to that.


Has nothing? As it seems you cannot even imagine that there are good
technical reasons why the features you have requested did not get into the
language. So whose mind was closed? Certainly not mine.
Show what you have got, where and how would you change
the language/the standard, what would it effect and why, what use
cases makes it possible etc. I am sure it is not only me, who will
be ready to look at it.


This issue is important to me so I probably will do that, when time
allows it.


Good. And since I have not see one single technical fact in your so-called
"argument", I will just bail out from here. Why? Because if it is not
important enough for you to come up with an organized description of what
you want, it is certainly not important for me to waste my time with endless
and meaningless discussions about the vague opinions of yours - instead of
facts. So if I will have time I will spend it now on reading proposals done
by people who take the time, so that I can (straw) vote on them responsibly.

--
Attila aka WW
Jul 22 '05 #40
In article <bv**********@news.net.uni-c.dk>, da*************@gmx.net
says...

[ ... ]
Then read it again. Several places Bjarne expresses that some things are
not exactly as he wishes, and may well be changed later.


Compare the copyright of the book to the date of the C++ standard, and
perhaps you'll start to realize why this is so.

Bjarne hasn't personally made the final decisions on the definition of
the language for quite some time now. He is a member of the standard
committee, and I'm sure his input is given considerable weight, but in
the end, the decisions are made on a more or less democratic model, not
an autocratic one.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Jul 22 '05 #41
In article <bv**********@news.net.uni-c.dk>, da*************@gmx.net
says...
Attila Feher wrote:

IIRC this is not true. Ariane was the crashed rocket, wasn't it? And that
has crashed because some program was not stopped after it was not in use
anymore, and sent out bad data. The thing which has crashed for the reason
you say was a Mars thing. Was it called Polar Lander?

Maybe you're right, but the point still stands.


That particular fiasco has little to do with types and such, though it
is interesting to note that almost all of the features that led to the
problem were _intended_ to prevent such things from happening.

Presumably the Ada feature you're talking about so positively is the
ability to do things like:

type Int1 is new integer; -- etc.

as opposed to:

type Int2 is integer;

but I'm not sure -- maybe you're just talking about a subtype, such as:

subtype digit is Integer range 0 .. 9;

While imitating the full capability of 'subtype' is probably difficult,
it sounds like you're interested primarily in a restricted range (e.g.
you also mention Pascal, which has a enumerated type that's quite
similar to enum in C++). Assuming that's the case, you can provide
roughly the same thing in C++, albeit with somewhat different syntax:

class out_of_bounds {};

template <typename type, type lower, type upper>
class ranged_subtype {
type value;
public:
operator type() { return value; }
operator=(type const &val) {
if ( val < lower || val > upper)
throw(out_of_bounds());
value = val;
}
ranged_subtype(type initial) {
if ( initial < lower || initial > upper)
throw(out_of_bounds());
value = initial;
}
};

#ifdef TEST
#include <iostream>

int main() {
typedef ranged_subtype<int, 0, 9> digit;

digit x = 1;

std::cout << x << std::endl;

digit y = 11;

std::cout << y << std::endl;

return 0;
}

#endif

which, when executed gives output something like this:
1

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
The second part is the response to the out_of_bounds exception that was
thrown but not caught -- obviously a real application would normally
want to catch and handle it appropriately.

That's not equivalent to a derived type in Ada, and doesn't give what
you seem to be asking for below: specifically, the ability to derive
directly from a built-in type, and then have assignments (for example)
type-checked, so you can't accidentally assign an object of the base
type directly to an object of the derived type.

At least from what I've seen, this isn't really a particularly great
loss. In point of fact, early in the history of C++ it _was_ seen as a
major problem, and a fair number of early class libraries included types
that were intended to cover this shortcoming, but including classes
(e.g. Integer) that were basically direct analogs of built-in types, but
were defined as classes so you could derive from them like you can from
any other class.

Such class libraries, however, have mostly gone the way of the dodo
bird, and for a simple reason: this capability seems useful at first,
but often leads quite quickly to problems -- much as is often the case
in Ada. The difference is that in Ada it's been a base part of the
language since the beginning, so it's essentially impossible to remove,
but in C++ it was never part of the language, so when problems arose it
was much easier to get rid of it.
I don't think you can find anything in that book about why you can't
have the compiler to that added type checking on types derived from
builtin types. I also doubt very much that you can come up with any good
reasons for leaving it out.


I can come up with some very good reasons for leaving it out. One is
that the language is already tremendously complex, and this would make
it even more so. Another is that experience with Ada has shown that
this ability isn't really as useful as you're implying.

As noted above, early users of C++ did see this as a problem, and did
provide a perfectly usable workaround to it -- but this practice has
almost entirely died (though it may be worth noting that Java has
standardized pretty much the same thing, so along with the built-in type
int, there's also a class Integer with similar characteristics, though
you can't derive from the former while you can from the latter).

In the end, however, if you're really convinced that this is important,
you have (at least) a couple of choices. The most obvious would be to
use a programming language (such as Ada) that already provides it.
Another would be to grab the sources to gcc (or some other C++ compiler
to which you can obtain source code) and modify it to allow what you
want. Given a successful implementation and a number (even a small
number) of happy users, I'm pretty sure you could write a proposal to
the C++ committee to get the possibility considered. I, for one, think
the committee would be badly mistaken to require such a thing of there's
nobody who's even willing to go to the trouble of trying it before they
propose requiring it.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Jul 22 '05 #42

This thread has been closed and replies have been disabled. Please start a new discussion.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.