Please, excuse me for my poor English.
There is a major difference between C++ correct construction like this:
struct Length { double l; operator =!?:%+-*/...(); };
struct Mass { double l; operator =!?:%+-*/...(); };
and the proposed extension
struct Length : public double ;
struct Mass : public double ;
And this difference lies on the keyword this
behavior. this
is a pointer and using a pointer let few chances to use registers for computations, because in usuals processors registers does not have address. Worst, using pointer make the compiler suspicous about the fact that two pointers may designate the same memory.
This will put an extraordinary burden on the compiler to optimize trivials ops.
Another problem is on the number of bugs: reproducing exactly all the behavior of operators is absolutly error prone (for ex making constructor explicit does not forbid all implicits cases). Probability of error while building such an object is quite high. It is not equivalent to have the possibility to do something thru hard work or to have it already done.
Compiler implementors would introduce type checking code (with maybe some errors, but compiler exactness is much better than client code, because of any bug in compiler generate countless errors cases), but main behavior of operation will remain exactly the same, with as few errors than usual.
The proposed alternate solution (using structs during debug phase and real floats when optimized ones) is interesting but has drawbacks: it's raise the probability to have bugs only in optimized version. And debugging optimized application is much costly.
One may implement a good proposal for @Rocketmagnet initial demand for integers types using :
enum class MyIntA : long {};
auto operator=!?:%+-*/...(MyIntA);
MyIntA operator "" _A(long);
The bug level will be quite high, like using single member trick, but compiler will treat thoses types exactly like built-in integers (including register capability & optimisation), thanks for inlining.
But this trick can't be used (sadly) for floating numbers, and the nicest need is obviously real valued dimensions checking. One may not mix up apples and pears: adding length and area is a common error.
Stroustrup' invocation by @Jerry is irrelevant. Virtuality is meaningful mainly for public inheritance, and the need is here toward private inheritance. Consideration around 'chaotic' C conversion rules (Does C++14 have anything not chaotic?) of basic type are also not useful : the objective is to have no default conversion rules, not to follow standard ones.
operator+
. I don't see the problem – CircostaintA+intB
would compile, which was what you wanted to avoid. – Circostaint
is expected. It can't reuse any int operators because doing so would enable the exact thing that the OP wanted to avoid. – Circostatypedef int CostumerId;
typedef int ProductId;
Costumer getCostumer(CostumerId cid);
ProductId pid = 10;
Costumer c = getCostumer(pid); // mistake allowed!!
if it wasclass CostumerId: int {}; and class ProductId: int {};
it wouldn't be allowed. If I just composeCostumerId { int id; }
I'll have to overload all operators to get the full functionality, like(pid++ == ++pid || pid != pid--).
– Slob