Consider the following code :
#include <iostream>
class Test
{
public:
Test() : a{ 0 }
{}
void print() const
{
std::cout << "a : " << a << std::endl;
}
void operator->()
{
a = 5;
}
void operator++()
{
++a;
}
public:
int a;
};
int main()
{
Test a;
a.print();
// Increment operator
a.operator++(); // CORRECT
++a; // CORRECT
a.print();
// Indirection operator
a.operator->(); // CORRECT
a->; // INCORRECT
a.print();
}
Why is the call to the second ->
operator incorrect? I know this usage of ->
is different from the general usage, but is such usage disallowed by the standard?
The sub-section on Class member access from Overloaded Operators from CPP standard draft (N4713) states this:
16.5 Overloaded operators
...
16.5.6 Class member access [over.ref]
1.operator->
shall be a non-static member function taking no parameters. It implements the class member access syntax that uses->
.postfix-expression -> template(opt) id-expression //This!! postfix-expression -> pseudo-destructor-name
An expression
x->m
is interpreted as(x.operator->())->m
for a class objectx
of typeT
ifT::operator->()
exists and if the operator is selected as the best match function by the overload resolution mechanism (16.3).
As you can see the id-expression
is very much needed if the ->
operator is overloaded.
Class member access [expr.ref/1] §7.6.1.5/1:
- A postfix expression followed by a dot
.
or an arrow->
, optionally followed by the keyword template ([temp.names]), and then followed by an id-expression, is a postfix expression. The postfix expression before the dot or arrow is evaluated; the result of that evaluation, together with the id-expression, determines the result of the entire postfix expression.
Names [expr.prim.id] (§7.5.4):
id-expression:
unqualified-id
qualified-id
An id-expression is a restricted form of a primary-expression. [ Note: An id-expression can appear after . and -> operators. — end note ]
An id-expression that denotes a non-static data member or non-static member function of a class can only be used:
2.1. as part of a class member access in which the object expression refers to the member's class or a class derived from that class, or
2.2. to form a pointer to member ([expr.unary.op]), or
2.3. if that id-expression denotes a non-static data member and it appears in an unevaluated operand.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With