As the title says, I find it useful to be able to overload operators. Is it possible to also change the way the operators are parsed by specifying the precedence and associativity of overridden operators?
No. Besides making code unreadable, it would make the language more ambiguous and deeply context-dependent because you would not be able to associate parameters with function calls until after you know all the operators available.
Consider the expression
a1 + a2 * a3
a* vars have type
A and you have overloadings
A operator+(A, A) // low precedence A operator*(A, A) // high precedence B operator+(A, A) // high precedence A operator*(B, A) // low precedence
This could be interpreted two different ways
operator+(a1, operator*(a2, a3))
operator*(operator+(a1, a2), a3)
With global precedence and associativity rules, the compiler can commit to the first interpretation during parse, but with overridable associativity/precedence, there's no way to figure out how to decompose tokens into function calls until you know all the available operator signatures.
This doesn't make the language impossible to parse (although there are more programs that have to be rejected as untypable) but it would make it slower to compile, and harder to read.
No. While it may at first sight seem to make sense, if you think a little more, it becomes muddy to the point that it's a bad idea.
First note that the language isn't defined by using a precedence grammar, but a more classic BNF. I'm not sure that the behavior of
?: is describable simply with a notion of priority and associativity.
But the major issue is that you are changing the priority and associativity of overloaded operators, not defining the priority and associativity of new operators used only for your types. Do you want your changes to be applicable for all uses, or just for your overload? You'll probably agree that the first option is a sure receipt for trouble. The other isn't much better. How to you know it's your overload which should be considered before doing overload resolution, which need parsing and thus associativity and priority to be known.
After reading some of the answers I think that, yes, it's time for me to look for down-votes.
<<represent bit shift with
+represent an arithmetic addition with
*represent dereference in
Despite this well established fact, there are still people claiming that overloading operator makes the code unreadable, and hence you should not ... blah blah ... and them must not ... blah blah ... and allowing to change precedence.
I find these arguments simply incoherent.
Operators are what makes entity to form expression that together defines an algebra. If an entity is not numeric, there is no need (I mean mathematical need) that such an algebra has to follow the same rule of natural numbers.
One of the reason that overloaded operators makes code hard to read is just because they are constrained to stay into the int semantic rules, even for things that do not have integer semantics and hence don't need that same syntax.
The answer to the question is:
NO: you cannot change precedence because the language specification doesn't allow it. Full stop.
And if you want to know why, you have to look at what the language is for.
C++ is already an complex language to parse and to translate.
By admitting "flex operators" (or even the definition of arbitrary infix-functions, like
<->, etc) the expression parser cannot anymore be deployed aside of types, and that was argued by language designer as a "feature with negative tradeoff" (it cost more to be deployed that the advantage it will ever give in real world). It's just "echonomy", not "morality".
All the "moral" aspect (don't do it because it hurts me) have nothing to do with the language and the operator abuse (I can even abuse of
for and use it instead of
if, but the problem is me , not the
for keyword. bashing it makes no sense as makes no sense to bash variable precedence even without knowing a proper use of it, for the simple reason that there cannot be a use - no matter if bad or good - being such a thing prohibited at the origin.) and are just related to language marketing.
C++ operator overloading was introduced to let scientists define private algebraic types. It is normal for them to ask more flexibility in defining and using symbols.
The Java language was defined to standardize coding around OOP. And since not all programmers wannabees are also scientific researchers, Java removed a number of features that can make the language deviate from the OOP paradigm it was philosophically designed around. And to motivate that to newbies, a dogmatic religion claiming "operator considered harmful", "global variables considered harmful" and so on was formalized ad deployed across schools.
And the bash against certain coding practices perfectly common in maths and science began just from there.
It is very simple to teach "no because is bad and makes you go to hell" instead to provide and compare rational ideas. And the result - 20 years later - is that if you do it, you really go to hell because all that religion believers (that nowadays are a huge amount of people) will make your life impossible.
And since Java became the first language newbies are exposed (and C++ eventually a second one) and its paradigms taught as dogmas to students, when those students become programmers they end up applying those "dogmas" to anything by an innate "extension".
After all no-one can give a rational reason abut his favorite football team. it just happen to be when you start follow it. There are no "technical reasons". Just passion (dogmas) and the stress to change (OOP methods forced even outside OOP context)
The reason you cannot change precedence is simply that the world retains that changing that dogma will cause too much stress to too much believers. But rationally speaking, there is no reason you can believe differently and makes you define a language with more freedom in usage.