Are . and -> in C and C++ really operators? - c++

you probably have been tought, are tought yourselves, that . and -> are operators which retrieve members of a struct (C) or class (C++).
However, I doubt they are operators - because, if they are operators, what are their input types? Furthermore, the identifiers on both sides are interdependent - a feature which for example the + operator lacks of.
If this is correct - in what sense are these still labeled as operator in practice, and what is their formal definition with regard to language theory.

You assume that the only types which can be passed as arguments to an operator are types that can be defined within the language.
I would argue that any type which can be recognised by the compiler may be passed as an argument, including internal types such as "identifier". The operator will have two arguments in its AST representation, which is enough to allow you to define semantics.
Another argument is that language theory may provide one set of definitions for your vocabulary, but it isn't the only one.
For example, an operator may be a man who works a machine. That definition has no relevance to programming theory, but it won't stop me using for keywords in a domain-specific language expressing something to do with machine operating. Similarly, the term "operator" has a wider definition in mathematics than that which is specific to programming theory - and that definition isn't invalidated simply by working with a programming language.
To put it another way - if you didn't call it an operator, what would you call it?
EDIT
To clarify, my first argument is referring to the syntax for using the operator (the call). These operators have right arguments which are identifiers - member names - which the C++ language cannot express using a data type. The C++ language does have member pointers, but they aren't the same thing as the members - just as a variable isn't the same as a pointer to that variable.
I assume that is what the question referred to. The right parameter of those operators has a type which cannot be expressed or manipulated normally in the language.
What happens when that syntax is mapped to an overloaded operator-> function is a different thing. The function isn't the operator - it's only how the operator gets implemented.

I think the fact that you can overload the -> operator using the "operator" keyword should be a dead giveaway.
Smart pointers do it pretty often:
template<class T>
struct myPtr {
T *operator ->() { return m_ptr; }
private:
T *m_ptr;
};
The . is not overloadable, but is also an operator by definition.

Hmmm...sizeof is an operator, what is its input type? I don't think the question is useful for distinguishing operators from non-operators in this context.
And that would be because what "operator" means in the context of a programming language is exactly what the author of the language says it means. Shades of Lewis Carroll here.

This reference says they're both operators in C++:
http://www.cplusplus.com/doc/tutorial/operators/
Is that not authoritative enough?

You can overload the -> operator: Wikipedia. That page also states that you can't overload dot. There's an example of -> overloading here:
class String // this is handle
{
...
Stringrep *operator -> () const { return b_; }
private:
Stringrep *b_;
}
The arrow works on the value to the left of the arrow and returns whatever the left hand side is "holding inside". Think of a smart pointer.

THe C++03 standard refers to both as operators.
Example:
...after the . operator applied to an expression of the type of its class...
If you are not comfortable with that terminology you can use the term punctuator for ..

Online C standard (n1256):
6.5.2.3 Structure and union members
Constraints
1 The first operand of the . operator shall have a qualified or unqualified structure or union
type, and the second operand shall name a member of that type.
2 The first operand of the -> operator shall have type ‘‘pointer to qualified or unqualified
structure’’ or ‘‘pointer to qualified or unqualified union’’, and the second operand shall
name a member of the type pointed to.
They are operators, and their input types are specified by the standard.

haha, i know people have already said this in a roundabout way but just to say it directly. In C terms, label-> is actually a shorthand for (*label). .That being said, . is the operator which references elements in a struct. Therefore, -> references an element in a pointer to a struct.

Related

Global Operator "->" overload C++

I want to overload "->" operator globally for pointers. Is it possible?
A *var1 = new A(21);
int x = var1->someInt;
In that code it has to be triggered when reaching "var1"s "someInt" variable.
Actually I am trying to check the pointer before reaching its members. Also, I am trying to implement this system on a written code, so I don't want to change too much thing in the actual code.
I want to overload "->" operator globally. Is it possible?
No it is impossible.
Perhaps you might define a "root" class in your library or program (which would define that operator ->), and have all your classes inherit from it.
BTW, I am not sure you will be able to define your isPointerValid function in all cases (including the address of valid automatic variables of any class type), and efficiently.
There are many cases where you could not define such a function (e.g. union-s used in tagged union types; you don't easily know what member of a union is currently active. arbitrary casts; ...); .
For existing code and classes, the builtin meaning of -> (which you usually cannot redefine) has already been used to compile the code using them.
As described in C++17 standard draft in section 16.5.6 (emphasis mine):
An operator function shall either be a non-static member function or
be a non-member function that has at least one parameter whose type
is a class, a reference to a class, an enumeration, or a reference to
an enumeration.
Hence, it is not possible to overload an operator which doesn't take any arguments.

overload "->" (member access) recursively

I am learning how to overload "->" and the documentation says that:
"operator-> is called again on the value that it returns, recursively, until the operator-> is reached that returns a plain pointer. After that, builtin semantics are applied to that pointer."
While it is clear what the documentation says, essentially that an overloaded "->" of a class could use itself a "special pointer" having itself an overloaded "->" that could give a "special pointer" etc etc until a "plain pointer" is found, I cannot find an example of a real use of it ( unless it is used to find a linked list last element ).
Could somebody explain what is the retionale behind the scenes, ( as that possibility isn't provided with "plain pointers" - so I dont' see any reason to provide it with "special pointers" ).
An example of real world use could help too, as probably I am missing a model where to apply the behaviour.
On the opposite side there could be the need to avoid that behaviour, how could it be done ?
Well, the -> operator works under rater special circumstances.
One can call it a pseudo-binary operator. According to its natural syntax pointer->member it takes two operands: a normal run-time operand on the left-hand side and a rather "strange" member name operand on the right-hand side. The "strangeness" of the second operand is rooted in the fact that C++ language has no user-accessible concept for representing such operands. There's nothing in the language that would express a member name as an operand. There's no way to "pass" a member name through the code to the user-defined implementation. The member name is a compile-time entity, remotely similar to constant expressions in that regard, but no constant expression in C++ can specify members. (There are expressions for pointers-to-members, but not for members themselves).
This creates rather obvious difficulties in specifying the behavior of overloaded -> operator: how do we connect what was specified on the right-hand side of -> (i.e the member name) to the code written by the user? It is not possible to do it directly. The only way out of this situation is to do it indirectly: force the user to channel the user-defined functionality of the overloaded -> operator into the functionality of some existing built-in operator. The built-in operator can handle member names naturally, through its core language capabilities.
In this particular case we have only two candidates to channel the functionality of the overloaded -> to: the built-in -> and the built-in .. It is only logical that the built-in -> was chosen for that role. This created an interesting side-effect: the possibility to write "chained" (recursive) sequences of overloaded -> operators (unwrapped implicitly by the compiler) and even infinitely recursive sequences (which are ill-formed).
Informally speaking, every time you use a smart pointer you make a real-world use of these "recursive" properties of overloaded -> operator. If you have a smart pointer sptr that points to a class object with member member, the member access syntax remains perfectly natural, e.g. sptr->member. You don't have to do it as sptr->->member or sptr->.member specifically because of the implicit "recursive" properties of overloaded ->.
Note that this recursive behavior is only applied when you use operator syntax for invoking the overloaded -> operator, i.e. the object->member syntax. However, you can also use the regular member function call syntax to call your overloaded ->, e.g. object.operator ->(). In this case the call is carried out as an ordinary function call and no recursive application of -> takes place. This is the only way to avoid the recursive behavior. If you implement overloaded -> operator whose return type does not support further applications of -> operator (for example, you can define an overloaded -> that returns int), then the object.operator ->() will be the only way to invoke your overloaded implementation. Any attempts to use the object->member syntax will be ill-formed.
I cannot find an example of a real use of it ( unless it is used to find a linked list last element ).
I think you're misunderstanding what it does. It isn't used to dereference a list element and keep dereferencing the next element. Each time you call operator-> you would get back a different type, the point is that if that second type also has an operator-> it will be called, which might return a different type again. Imagine it being like x->->->i not x->next->next->next if that helps
An example of real world use could help too, as probably I am missing a model where to apply the behaviour.
It can be useful for the Execute Around Pointer pattern.
On the opposite side there could be the need to avoid that behaviour, how could it be done ?
Call the operator explicitly:
auto x = p.operator->();

Why can't everything be overloaded in C++?

It is reasonable that sizeof and typeid cannot be overloaded, but I can't see the harm in overloading ?:, .* and .. Are there technical reasons for this?
To quote Bjarne Stroustrup:
There is no fundamental reason to
disallow overloading of ?:. I just
didn't see the need to introduce the
special case of overloading a ternary
operator. Note that a function
overloading expr1?expr2:expr3 would
not be able to guarantee that only one
of expr2 and expr3 was executed.
...
Operator . (dot) could in principle be
overloaded using the same technique as
used for ->. However, doing so can
lead to questions about whether an
operation is meant for the object
overloading . or an object referred to
by . ... This problem can be solved in
several ways. At the time of
standardization, it was not obvious
which way would be best.
Source
If you overload ., how would you access class members? What would be the meaning of obj.data?
What would the syntax be?
In fact, there are good reasons for not overloading any operator
which doesn't evaluate all of its operands: you shouldn't
overload && or || either (except in special cases). You can't
simulate this with an overloaded operator. Consider something
like:
p != NULL ? defaultValue : p->getValue()
where the type of defaultValue or p->getValue() causes overload
resolution to pick up your overload. It's a common idiom, but
it can't be made to work if you overloaded ?:.
Here's some reading material C++ FAQ Lite :)
In general there would be no benefit to overloading the operators above. What additional semantics would you be trying to implement?
The reason for overloading operators is to provide intuitive syntax to the user of your class. For example, it makes sense to overload + and += for strings. It's obvious to another developer what that means.
It's really not obvious what you would overload ?: for ... That said there are no technical reasons I am aware of that prevented these operators from being overloaded.
Overloading the -> operator allows for reference counted pointers to be created such as boost::shared_ptr. The concept of 'negating' an object might have different meanings in different contexts, so it's reasonable to occasionally overload this operator.
Defining "operator bool" is enough for ?: to work.
For operator . think of this: SomeClass."SomeString!!"
These overloadings prohibit compiler's lexer from parsing the file correctly.
The reason you can overload most operators is to be able to simulate built in types. Since none of the built in types can use the . operator, it wouldn't serve any purpose. operator* and operator-> are there so you can make your own pointer classes. All the math and boolean operators are there to be able to make your own numeric classes.

subscript operator postfix

The C++ standard defines the expression using subscripts as a postfix expression. AFAIK, this operator always takes two arguments (the first is the pointer to T and the other is the enum or integral type). Hence it should qualify as a binary operator.
However MSDN and IBM does not list it as a binary operator.
So the question is, what is subscript operator? Is it unary or binary? For sure, it is not unary as it is not mentioned in $5.3 (at least straigt away).
What does it mean when the Standard mentions it's usage in the context of postfix expression?
I'd tend to agree with you in that operator[] is a binary operator in the strictest sense, since it does take two arguments: a (possibly implicit) reference to an object, and a value of some other type (not necessarily enumerated or integral). However, since it is a bracketing operator, you might say that the sequence of tokens [x], where x might be any valid subscript-expression, qualifies as a postfix unary operator in an abstract sense; think currying.
Also, you cannot overload a global operator[](const C&, size_t), for example. The compiler complains that operator[] must be a nonstatic member function.
You are correct that operator[] is a binary operator but it is special in that it must also be a member function.
Similar to operator()
You can read up on postfix expressions here
I just found an interesting article about operator[] and postfix expression, here
I think it's the context that [] is used in that counts. Section 5.2.1 the symbol [] is used in the context of a postfix expression that is 'is identical (by definition) to *((E1)+(E2))'. In this context, [] isn't an operator. In section 13.5.5 its used to mean the subscripting operator. In this case it's an operator that takes one argument. For example, if I wrote:
x = a[2];
It's not necessarily the case that the above statement evaluates to:
x = *(a + 2);
because 'a' might be an object. If a is an object type then in this context, [] is used as an subscript operator.
Anyway that's the best explanation I can derive from the standard that resolves apparent contradictions.
If you take a close look to http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B it will explain you that standard C++ recognize operator[] to be a binary operator, as you said.
Operator[] is, generally speaking, binary, and, despite there is the possibility to make it unary, it should always be used as binary inside a class, even because it has no sense outside a class.
It is well explained in the link I provided you...
Notice that sometimes many programmers overload operators without think too much about what they are doing, sometimes overloading them in an incorrect manner; the compiler is ease is this and accept it, but, probably, it was not the correct way to overload that operator.
Following guides like the one I provided you, is a good way to do things in the correct manner.
So, always beware examples where operators are overloaded without a good practice (out of standard), refer, first to the standard methods, and use those examples that are compliant to them.

What is the official name of C++'s arrow (->) operator?

I always call it the "arrow operator", but I'm sure it has an official name. I quickly skimmed the C++ standard and didn't see it mentioned by name.
The C++ standard just calls it "arrow" (§5.2.5).
Bjarne Stroustrup calls it the "structure pointer dereference" operator (TC++PL Special Edition, p. 102). In the index he refers to it as the "member access" operator.
Not sure if this is "official" but the guy did write the language, after all.
The official name for this operator is class member access operator (see 5.2.5). Although this name is attached to both . and -> operators, meaning that it's more of a group name. The . is also referred to as dot operator and -> as arrow operator in the standard text.
Added later: The above applies to C++ standard. C standard refers to -> as arrow operator in the Index only. The main text of the document doesn't seem to use any specific name.
According to Wikipedia's list of operators in C and C++, it's called "member by pointer".
But to be totally honest, I've always called it "arrow". For example, if I had the code a->b, I would read that as "a arrow b".
Its just the dit (ie not dot).
These terms are in no way official, but I'd call the dot operator the direct (class) member access operator and the arrow operator the indirect (class) member access operator to clarify their relationship with the indirection operator.
I've heard it referred to a few different ways, was never sure any one in particular was more official than another.
Member Selection Operator
Pointer Dereferencing Operator
"the arrow thingy"
and I'm sure there are others. personally I'm less concerned about what its called in a book or an official spec and more concerned that people know what I mean when I refer to it, so in my opinion "arrow thingy" is the best name for it since its the easiest to understand clearly what is being referred to.
The index to ISO/IEC 9899:1999 (the C99 standard) has three index entries for 'arrow operator' (in its own right, and under 'union' and 'struct'), and refers to section 6.5.2.3 (Structure and union members, in the section on Postfix operators). However, there is no mention of 'arrow' in section 6.5.2.3 or anywhere else in the standard than the index (every other appearance of 'arrow' is as part of 'narrow' or a derivative of narrow).
Arrow is therefore semi-officially sanctioned in the C standard (the index is not normative or standard setting, though).
Dereference Pointer
There was a recent question regarding how the operator is "pronounced" in context.
Consider the multiplication operator which is pronounced "times" in context.
I consider both member access operators {. ->} to indicate possession so I pronounce them as a possessive on the object.
For example...
fido->collar()
...would be pronounced as "fido's collar".
On the other hand possession isn't appropriate for verbs so...
fido->run()
...would be pronounced as "fido runs".
The ISO C standard calls it the->operator or the member-access->operator. So apparently it does not have an "official" name in C.
Personally, I just say pointer or arrow.