On Mon, 29 Mar 2010 00:46:20 +0400, Don <nos...@nospam.com> wrote:

so wrote:
Hello Don, finally!
It is hard to explain yourself when you don't know the people you talk have numeric coding background. Since we know you have done much numeric and generic coding, it will be enough for me if you understand what i mean/ask/want, and say what i am talking is ridiculous, or think that i am trolling, just say so and i shut up! :)

You're definitely not trolling! I'm not 100% sure of which issue you're referring too, but I'm aware of a few, for example:

(1) Converting a floating point literal into a double literal is usually not lossless. 0.5f, 0.5, and 0.5L are all exactly the same number, since they are exactly representable.
But 0.1 is not the same as 0.1L.
So it's a bit odd that this silent lossless conversion is taking place.
It does have a very strong precedent from C, however.

(2) The interaction between implicit casting and template parameters is quite poor. Eg, the fact that '0' is an int, not a floating point type, means that something simple like:
  add(T)(T x) if (isFloatingPoint!(T))
doesn't work properly. It is not the same as:
add(real x)
since it won't allow add(0).

Which is pretty annoying. Why can't 0 just mean zero???

At the beginning the question in my mind was, why can't we do this the way it works in math :

[Real numbers] contains [Integers] contains [Natural numbers]

So, when a compiler see 0, which is the element of all above, it should classify it as :
1st degree. [floating point type, integer, natural number]
When it encounters say, -3, it will be :
2nd degree. [floating point type and integer]
And finally when it encounters something like 4.0, it will be :
3rd degree. [floating point type]

With these in mind, the prototype :

T foo(T)(T m) {}, should be able to take all three degrees of types above.

We go abit further and see what it actually is :

T foo(T)(T m) {
T n = m * 5 - 4 * 7 / 2; // numbers belongs all the systems above, this line should work for every T
        T k = n / 20; // same.
        return n + k; // same.
}

"T n = m * 5 - 4 * 7 / 2;"
m is here in the type of T,
* operator has a generic operand 5, convert it to T, if you can't, pop error. - operator has a generic operand (4 * 7 / 2), expect it in the and keep parsing.

Again, in the code above, none of the constants is a native type, as in 5 is not int, it is a generic constant which belongs all systems above.
What this means?

calling foo(0.0f) is actually :
float foo(float m) {
        float n = m * 5.0f - 4.0f * 7.0f / 2.0f;
        float k = n / 20.0f;
        return n + k;
}

m is here float and operation * has a generic operand

There wasn't a single implicit cast and the code was perfectly generic.
calling foo(0) will pass the "if(isFloatingPoint!(T))" contract, since 0 belongs to all, but compiler will be unable to resolve the final type which is to be instantiated.

But coming with something like this would be suicide since i already got enough treatment for the lighter syntax :P
Sorry for the long post!

Thanks.

--
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/

Reply via email to