Defaul compiler generates the reference operator (In C++)? - c++

All the authors write that, by default, the compiler generates
1. the default constructor
2. copy constructor
3. assignment operator
4. destructor
The other day a friend of mine invited for an interview and there he was told that by default, the compiler generates still one function reference operator (operator &()). it is in fact so?

No, that is not true. If there is no operator& present, then the one in the core language is used.
N3485 13.3.1.2 [over.match.oper]/1-2 (emphasis mine):
If no operand of an operator in an expression has a type that is a class or an enumeration, the operator is assumed to be a built-in operator and interpreted according to Clause 5. [ Note: Because ., .*, and :: cannot be overloaded, these operators are always built-in operators interpreted according to Clause 5. ?: cannot be overloaded, but the rules in this subclause are used to determine the conversions to be applied to the second and third operands when they have class or enumeration type (5.16). —end note ]
If either operand has a type that is a class or an enumeration, a user-defined operator function might be declared that implements this operator or a user-defined conversion can be necessary to convert the operand to a type that is appropriate for a built-in operator. In this case, overload resolution is used to determine which operator function or built-in operator is to be invoked to implement the operator.
You can also see this in that the functions implicitly declared for you are listed as the "Special Member Functions (Clause 12), which makes no reference to operator&.

Related

What is "Unary Constructor"?

Here in this link it says:
The static_cast keyword can be used for any normal conversion between
types. Conversions that rely on static (compile-time) type
information. This includes any casts between numeric types, casts of
pointers and references up the hierarchy, conversions with unary
constructor, conversions with conversion operator. For conversions
between numeric types no runtime checks if data fits the new type is
performed. Conversion with unary constructor would be performed even
if it is declared as explicit.
Also here:
To interoperate well with other CLS-compliant languages, you may wish
to wrap each user-defined unary constructor for a given class with a
corresponding convert-from operator.
What do they mean by "Unary Constructor"?
Unary means one, so what they are talking about is a constructor with a single parameter. The standard name for such a thing is a conversion constructor.
Unary refers to one or singular, so a 'Unary constructor' ideally refers to a constructor with a single parameter.

C++ conditional operator with void operand(s)

I’m trying to understand the following excerpt from the C++ standard (ISO/IEC 14882:2003, newer versions say essentially the same):
5.16 Conditional operator
2 If either the second or the third operand has type (possibly cv-qualified) void, then the lvalue-to-rvalue
(4.1), array-to-pointer (4.2), and function-to-pointer (4.3) standard conversions are performed on the second
and third operands, ...
I am inclined to thinking that in this context, when an operand is a function call, then the type of the operand is taken to be (although it is not) the function return type. If that is so, then that yields an example of a void type.
I also imagine that a throw expression could also be surmised to have type void in this context, independently of the type of the throw operand. That would then be another example.
Are my two assumptions right? Are there any other cases?
Many thanks
About throw, yes, there is no result, so the type is void and the type of the throw operand is irrelevant. I'm not sure how it could be relevant so that question seems odd.
About functions, I don't know why you say the type of the operand is not the function return type if the operand is a function call. What else would it be? It's where the operand is a function (as opposed to a function call) that function-to-pointer conversion would kick in.
The result type of the conditional operator depends on the type of it's operands.
I think the special language around one of the operands being void is simply that the result of the conditional operator is then void, so the rules about possibly performing conversions of operands of different types are not relevant.

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.

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

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.

Why can some operators only be overloaded as member functions, other as friend functions and the rest of them as both?

Why can some operators only be overloaded as member functions, other as non-member "free" functions and the rest of them as both?
What is the rationale behind those?
How to remember which operators can be overloaded as what (member, free, or both)?
The question lists three classes of operators. Putting them together on a list helps, I think, with understanding why a few operators are restricted in where they can be overloaded:
Operators which have to be overloaded as members. These are fairly few:
The assignment operator=(). Allowing non-member assignments seems to open the door for operators hijacking assignments, e.g., by overloading for different versions of const qualifications. Given that assignment operators are rather fundamental that seems to be undesirable.
The function call operator()(). The function call and overloading rules are sufficiently complicated as is. It seems ill-advised to complicate the rules further by allowing non-member function call operators.
The subscript operator[](). Using interesting index types it seems that could interfere with accesses to operators. Although there is little danger of hijacking overloads, there doesn't seem to be much gain but interesting potential to write highly non-obvious code.
The class member access operator->(). Off-hand I can't see any bad abuse of overloading this operator a non-member. On the other hand, I also can't see any. Also, the class member access operator has rather special rules and playing with potential overloads interfering with these seems an unnecessary complication.
Although it is conceivable to overload each of these members are a non-member (especially the subscript operator which is works on arrays/pointers and these can be on either side of the call) it seems surprising if, e.g., an assignment could be hijacked by a non-member overload which which is a better match than one of the member assignments. These operators are also rather asymmetric: you generally wouldn't want to support conversion on both sides of an expression involving these operators.
That said, e.g., for a lambda expression library it would be nice if it were possible to overload all of these operators and I don't think there is an inherent technical reason to preventing these operators from being overloadable.
Operators which have to be overloaded as non-member functions.
The user-defined literal operator"" name()
This operator is somewhat of an odd-ball and, arguably not really really an operator. In any case, there is no object to call this member on for which members could be defined: the left argument of user-defined literals are always built-in types.
Not mentioned in the question but there are also operator which can't be overloaded at all:
The member selector .
The pointer-to-member object access operator .*
The scope operator ::
The ternary operator ?:
These four operators were considered to be too fundamental to be meddled with at all. Although there was a proposal to allow overloading operator.() at some point there isn't strong support doing so (the main use case would be smart references). Although there are certainly some contexts imaginable where it would be nice to overload these operators, too.
Operators which can be overloaded either as members or as non-members. This is the bulk of the operators:
The pre- and post-increment/-decrement operator++(), operator--(), operator++(int), operator--(int)
The [unary] dereference operator*()
The [unary] address-of operator&()
The [unary] signs operator+(), operator-()
The logical negation operator!() (or operator not())
The bitwise inversion operator~() (or operator compl())
The comparisons operator==(), operator!=(), operator<(), operator>(), operator<=(), and operator>()
The [binary] arithmetic operator+(), operator-(), operator*(), operator/(), operator%()
The [binary] bitwise operator&() (or operator bitand()), operator|() (or operator bit_or()), operator^() (or operator xor())
The bitwise shift operator<<() and operator>>()
The logic operator||() (or operator or()) and operator&&() (or operator and())
The operation/assignment operator#=() (for # being a suitable operator symbol()
The sequence operator,() (for which overloading actually kills the sequence property!)
The pointer pointer-to-member access operator->*()
The memory management operator new(), operator new[](), operator new[](), and operator delete[]()
The operators which can be overloaded either as members or as non-members are not as necessary for fundamental object maintenance as the other operators. That is not to say that they are not important. In fact, this list contains a few operators where it is rather questionable whether they should be overloadable (e. g., the address-of operator&() or the operators which normally cause sequencing, i. e., operator,(), operator||(), and operator&&().
Of course, the C++ standard doesn't give a rationale on why things are done the way they are done (and there are also no records of the early days when these decisions where made). The best rationale can probably be found in "Design and Evolution of C++" by Bjarne Stroustrup. I recall that the operators were discussed there but there doesn't seem to be an electronic version available.
Overall, I don't think there are really strong reasons for the restrictions other than potential complication which was mostly not considered worth the effort. I would, however, doubt that the restrictions are likely to be lifted as the interactions with existing software are bound to change the meaning of some program in unpredictable ways.
The rationale is that it would not make sense for them to be non-members, as the thing on the left-hand side of the operator must be a class instance.
For example, assuming a class A
A a1;
..
a1 = 42;
The last statement is really a call like this:
a1.operator=(42);
It would not make sense for the thing on the LHS of the . not to be an instance of A, and so the function must be a member.
Because you can't modify the semantics of primitive types. It wouldn't make sense to define how operator= works on an int, how to deference a pointer, or how an array access works.
Here is one example:
When you are overloading the << operator for a class T the signature will be:
std::ostream operator<<(std::ostream& os, T& objT )
where the implementation needs to be
{
//write objT to the os
return os;
}
For the << operator the first argument needs to be the ostream object and the second argument your class T object.
If you try to define operator<< as a member function you will not be allowed to define it as std::ostream operator<<(std::ostream& os, T& objT).
This is because binary operator member functions can only take one argument and the invoking object is implicitly passed in as the first argument using this.
If you use the std::ostream operator<<(std::ostream& os) signature as a member function you will actually end up with a member function std::ostream operator<<(this, std::ostream& os) which will not do what you want.
Therefore you need a operator that is not a member function and can access member data (if your class T has private data you want to stream, operator<< needs to be a friend of class T).