Special semantics for arrow`->` operator and dot`.` operator in C++
20 Apr 2015 C++Ever tried to overload operator->
? If you haven’t, let me tell you this doesn’t work like other overloaded operators.
For example let us take an operator like operator*
. What do you expect this to return? Lets say we have a pointer to class A
, ptr_a
. The operator*
is already overloaded in class A
. What would (*ptr_a).foo();
return?
By simple logic, *ptr_a
will return the reference to the object ptr_a
points to(say obj_a
). And as expected the statement will execute as (obj_a).foo()
.
However, this logic doesn’t apply to the operator->()
. As quoted from stack overflow,
Theoperator->
has special semantics in the language in that, when overloaded, it reapplies itself to the result. While the rest of the operators are applied only once,operator->
will be applied by the compiler as many times as needed to get to a raw pointer and once more to access the memory referred by that pointer.In the previous example, in the expressionstruct A { void foo(); }; struct B { A* operator->(); }; struct C { B operator->(); }; struct D { C operator->(); }; int main() { D d; d->foo(); }
d->foo()
the compiler will take the objectd
and applyoperator->
to it, which yields an object of typeC
, it will then reapply the operator to get an instance ofB
, reapply and get toA*
, after which it will dereference the object and get to the pointed data.d->foo(); // expands to: // (*d.operator->().operator->().operator->()).foo(); // D C B A*
And guess what? You can’t overload operator.(). I would like to quote Bjarne Stroustrup here from The Design and Evolution of C++, page 242, section 11.5.2 Smart References.
When I decided to allow overloading of operator ->, I naturally considered whether operator . could be similarly overloaded.
At the time, I considered the following arguments conclusive: If obj is a class object then obj.m has a meaning for every member m of that object’s class. We try not to make the language mutable by redefining built-in operations (though that rule is violated for = out of dire need, and for unary &).
If we allowed overloading of . for a class X, we would be unable to access members of X by normal means; we would have to use a pointer and ->, but -> and & might also have been re-defined. I wanted an extensible language, not a mutable one.
These arguments are weighty, but not conclusive. In particular, in 1990 Jim Adcock proposed to allow overloading of operator . exactly the way operator -> is.
comments powered by Disqus