Error in C compiler but not in c++ compiler - c++

int a=5;
++a=a;
Please find the above code segment. The code is ok for the c++(g++) compiler but shows error while using c (gcc) compiler. May I know the reason for this?
The error in c compiler is "lvalue required as left operand of assignment".

There is operator overloading in C++ (and you can overload pre-increment also), so to achieve some additional goals pre-increment operator returns lvalue in C++.
For example:
Your class may implement some pointer functionality and may need:
pre-increment for pointer shifting;
assignment operator for assignment to pointer value (value by the address).
Pre-increment may be useful in this case.
Abstract code example:
class MyIntPtr {
int *val;
...
public:
MyIntPtr(int *p) { ... };
MyIntPtr &operator++() { ++val; return *this; };
void operator=(int i) { *val = i; }
...
};
...
int array[10];
MyIntPtr ptr(array);
for(int i = 0; i < sizeof array; ++i)
++ptr = i;

Because in C++, the preincrement operator yields an lvalue, whereas in C, it's an rvalue.

Related

How does the syntax for overloading post-increment operator in c++ work?

int operator++(int){
//relevant code
}
I dont seem to understand the workings of the code for overloading post increment operator given
above
I know that the int as a dummy parameter is given to differentiate between pre-increment and post increment operator overloading.
If a is a object of the class in which these operators are overloaded ,both ++a and a++ should have a equivalent representation as a.operator++()(as per my understanding ),how does the int parameter help in resolving it as a post increment operator?
-A c++ beginner
If a is a object of the class in which these operators are overloaded
,both ++a and a++ should have a equivalent representation as
a.operator++()(as per my understanding ),how does the int parameter
help in resolving it as a post increment operator?
The post increment operator can be called with a dummy int argument but normally this isn't what you would do. In the following, typically you would define void foo::operator++(int) so that you can make a call like (1) but (2) is legal.
#include<iostream>
struct foo {
void operator++() {
std::cout << "pre\n";
}
void operator++(int) {
std::cout << "post\n";
}
};
int main() {
foo a;
// these yield: pre
++a;
a.operator++();
// these yield post:
a++; // (1)
a.operator++(int{}); // (2)
}
When the compiler sees ++a, and a is not a built-in type, then the compiler looks for either a::operator++() or operator++(a&) and if found then calls it.
When the compiler sees a++, and a is not a built-in type, then the compiler looks for either a::operator++(int) or operator++(a&, int) and if found then calls it.
See Increment/decrement operators on cppreference.com for more details.

About the C++ overloaded operators

Running the program below on my computer
#include <iostream>
class Int {
public:
Int(int x) : val{x} {}
Int operator++() {
std::cout << "Int::operator++()\n";
return ++val;
}
friend Int operator+(Int a, Int b) {
std::cout << "operator+(Int, Int)\n";
return a.val + b.val;
}
friend Int operator*(Int a, Int b) {
std::cout << "operator*(Int, Int)\n";
return a.val * b.val;
}
private:
int val;
};
int main()
{
Int a = 1, b = 2;
b = ++a + b * b;
return 0;
}
I got this output:
operator*(Int, Int)
Int::operator++()
operator+(Int, Int)
As far as I known, the prefix ++ has higher precedence than binary *. But in the output shown above, the prefix ++ is called after the binary *! Is it because the compiler treats the operator+ as a function call (which leads to Unspecified Behavior)? Can I always consider an overloaded operator as a function (which makes the behavior of x = x++ well-defined when x is an Int)?
Thanks!
Is it because the compiler treats the operator+ as a function call (which leads to Unspecified Behavior)?
Yes. But note that it doesn't matter if ++a is evaluated after b * b, because in the end, those two are added correctly, which respects operator precedence rules.
Your expression without the assignment is equivalent to:
operator+(a.operator++(), operator*(b, b))
The order of evaluation of function arguments is unspecified, so technically, ++a can be evaluated before b * b, but also the other way around.
Can I always consider an overloaded operator as a function (which makes the behavior of x = x++ well-defined when x is an Int)?
Yes and no. If Int does the same thing as the "normal" operators would do, then no (until C++17), because that would be undefined behavior. But if Int doesn't change x in x++ for example, then yes.
As far as I known, the prefix ++ has higher precedence than binary *.
Higher precedence doesn't mean that the prefix increment will be called before the multiplication operator, but in which order the parameters are bound to the corresponding operation.

Why is & needed for member function pointers, not for normal function pointers?

I understand my second statement that "why & is not needed for normal function pointers" because function name itself is address of the function.
What I do not understand is why '&' is strictly needed for member function pointers?
Examples:
Normal function pointers:
int add(int a, int b) {
return (a + b);
}
int (*fp)(int, int);
fp = add;
(*fp)(2, 3) // This would give me addition of a and b, i.e. 5
Member function pointers:
class ABC {
public:
int i;
ABC() { i = 0; }
int addOne(int j) {
return j + 1;
}
};
// Member function pointer
int (ABC::*mfp)(int);
// This is what I am talking about. '&' in below line.
mfp = &ABC::addOne;
ABC abc;
std::cout << (abc.*mfp)(2) << std::endl;
It seems to me that the address-of operator is necessary for member function pointers because the right-hand side (rhs) of the declaration is a constant rather than a variable.
We wouldn't say
int (ABC::*mfp)(int);
mfp = ABC::addOne();
because that would be to invoke a function.
Furthermore, the scope resolution operator :: has the highest precedence in the C++ table of operator precedence:
https://github.com/MicrosoftDocs/cpp-docs/blob/master/docs/cpp/cpp-built-in-operators-precedence-and-associativity.md
The :: operator is evaluated before any other operators are on the rhs. I suppose the complier wonders "Hmmmm...what's that? That should be a function, but..." and then sees the address-of operator and knows what the developer needs.

Why does "return *this" return a reference?

In my C++ class they were discussing how to create an assignment operator. At the end of the assignment was the line "return *this," which they said returned a reference to the object that "this" points to. Why does it return a reference? If "this" is being dereferenced, shouldn't it just return the object?
A function returns a reference if its declaration (i.e. its signature) tells so.
So (assuming a class Foo) if a function is declarated
Foo fun();
then it returns a value (with copying, etc..)
But if it is declared as
Foo& fun();
or as
const Foo& fun();
a reference is returned.
The statement return *this; don't define by itself if a reference or a value is returned.
It returns the current instance of the type MyClass you are in. It's returned as reference because the assignment operator was explicitly told to return a reference.
MyClass& operator = (MyClass& other) { return *this; }
Note the & after MyClass as the return value. A reference is returned.
Unless the & weren't there right before operator, the instance would be returned by value.
The expression *this
At the end of the assignment was the line "return *this," which they said returned a reference to the object that "this" points to
They were wrong.
Why does it return a reference?
It doesn't.
If "this" is being dereferenced, shouldn't it just return the object?
Yes!
Dereferencing a pointer yields an lvalue. That means that the result of *this is the actual object that this points to. It's not a reference, but it's not a copy either.
[C++11: 5.3.1/1]: The unary * operator performs indirection: the expression to which it is applied shall be a pointer to an object type, or a pointer to a function type and the result is an lvalue referring to the object or function to which the expression points. If the type of the expression is “pointer to T,” the type of the result is “T.” [..]
It can be hard to conceptualise, since you can never do this yourself in code; it's just a feature of the * operator for native pointers, and has been since C.
Returning from operator=
Because you can't do it yourself, conventionally you'd bind that lvalue expression to a reference in order to use it in different contexts. For example, the expression *this in return *this gets bound to the return type of the function that you're returning from; in this case, an assignment operator.
Now, we could have the assignment operator return by value in which case an object copy would be made from the lvalue that comes from *this; however, for an assignment operator we usually return by reference so that we avoid an almost-certainly needless copy, and can perform chaining:
Type a, b, c;
c = b = a;
It's a convention with benefits, and no downsides. Can you think of a situation when you'd want op= to return by value?
Every dereferenced pointer is a reference to its pointee, else you'd 'loose' the pointee you're pointing to.
Invoke method twice on the same object, using a pointer and a reference:
MyClass* objPtr = .... ;
objPtr->doSomething();
MyClass& objRef = *objPtr;
objRef.doSomething();
Invoke method on distinct objects; original and copy:
MyClass* objPtr = .... ;
objPtr->doSomething();
MyClass objCopy = *objPtr; //here, the reference is passed to the (implicit or implemented) copy constructor if possible, else a compile time error occurs.
objCopy.doSomething();
That means, if you return a reference from an operator method which has MyClass (rvalue) instead of MyClass& (lvalue) as return type, a copy of *this (MyClass&) is created by reference (leaving aside return value optimizations and rvalue references).
This is useful for non modifying const methods such as + and - which have a new value as result while leaving the object on which this method was invoked unmodified.
Operators like += and your assignment operator modify the object inplace by convention and should therefore return a reference to allow expressions like primitive types support it, since a temporary copy may vanish and cause unexpected results:
Consider this expression:
int i = 4;
int r = (i += 3) <<= 2;
The result r is 28 (added and shifted inplace).
What is the value of i? 28 too, what else.
But what if hypothetically int::operator+= would return a copy of itself instead of a reference to itself?
The result r would be 28 too.
But the value of i?
It would be 7, since the inplace left shift was applied to a temporary int returned from the addition which gets assigned to r after that.
Continuing the assumption, the error may have the same effect (except for the value in i) as this expression:
int r = (i + 3) <<= 2;
But luckily, the compiler will complain, that he doesn't have an lvalue reference from (i + 3) to do the shift/assignment operation.
But play with this:
class Int
{
private:
int val;
public:
Int(int val) :
val(val)
{
}
Int operator+(const Int& other)const
{
return val + other.val;
}
Int operator+(int prim)const
{
return val + prim;
}
Int& operator+=(const Int& other)
{
val += other.val;
return *this;
}
//Error here, Int& would be correct
Int operator+=(int prim)
{
val += prim;
return *this;
}
Int operator<<(const Int& other)const
{
return val << other.val;
}
Int operator<<(int prim)const
{
return val << prim;
}
Int& operator<<=(const Int& other)
{
val <<= other.val;
return *this;
}
Int& operator<<=(int prim)
{
val <<= prim;
return *this;
}
operator int()const{
return val;
}
};
int main()
{
Int i = 4;
Int r = (i += 3) <<= 2;
cout << i;
return 0;
}
In C++ the * always means a value, in fact you can look to en English interpretation for these operators as follows:
&: the address of
*: the value of
So when you say &x it means "the address of x" and when you say *x it means "the value that x points to". So *this will always return a value.
Just be sure that the function itself that the hosts the returning is not a reference function. Please remember that in C++ you can create functions with the & or the * operators as well.

Commutative property a[i] == i[a]

For a built in type integer array say
int a[10];
int i = 2;
a[i] = 10;
alternatively
i[a] = 10;
because
a[i] is a postfix expression that is *(a+i) or *(i+a) because commutative property of addition.
I want to achieve that for a userdefined type say
class Dummy
{
//
};
Is it possible?
If yes then how?
If no then why?
EDIT :-
I know it is ugly but following code compiles :-
g++ -dumpversion
4.3.3
#include <stdio.h>
#include<iostream>
#include <string.h>
#include <malloc.h>
using namespace std;
int main()
{
string ArrayS[10];
2[ArrayS] = "ADASD" ;
cout << 2[ArrayS] << endl;
return 0;
}
It is impossible because "operator[] shall be a non-static member function with exactly one parameter" (standard §13.5.5/1), so you cannot define it such that the first argument is of native scalar type.
(Furthermore, a nonstatic operator overload call is interpreted as a member call, so the first operand cannot be implicitly converted, unlike a free function overload. This is one reason why free function overloads are preferred when possible.)
For better or worse, index[ object ] is a way to ensure that no operator[] overload gets called.
However.
"The expression E1[E2] is identical (by definition) to *((E1)+(E2))" (§5.2.1) and operator+ can be overloaded so long as one side is not native type. This leaves two options vulnerabilities: the "array" must be a class, or the "index" must be a class or enum.
You would then have to define a proxy type to hold the result of "addition," which defines an operator* overload. GCC does not support this, however. I'll look deeper into other platforms and references.
Edit: Ah, §13.6/13 overrides 5.2.1 and declares that, for the sake of interpreting an expression involving class or enumeration type, there are functions T& operator[](std::ptrdiff_t, T*); and T& operator[](T*, std::ptrdiff_t);. So that's that.
With C++, nothing is impossible. It is however, a terrible terrible idea. Don't do this.
#include <memory>
#include <stdlib.h>
#include <stdio.h>
void *aligned_malloc( size_t bytes, size_t alignment ) {
void *p = malloc( bytes + alignment ), *pa = reinterpret_cast<void*>( reinterpret_cast<size_t>(p) + alignment &- alignment );
reinterpret_cast<void**>(pa)[-1] = p;
return pa;
}
void aligned_free( void *pa ) {
void *p = reinterpret_cast<void**>(pa)[-1];
free( p );
}
struct SupportReverseIndexer
{
class IndexerReversal
{
static const size_t alignment;
friend struct SupportReverseIndexer;
friend class std::auto_ptr<IndexerReversal>;
struct SupportReverseIndexer* const m_parent;
IndexerReversal(struct SupportReverseIndexer* parent) : m_parent(parent) {}
void* operator new(size_t bytes) { return aligned_malloc(bytes, alignment); }
void operator delete(void* p) { aligned_free(p); }
static struct SupportReverseIndexer* getParent(IndexerReversal* pThis)
{
size_t iThis = reinterpret_cast<size_t>(pThis);
iThis += alignment >> 1;
iThis &= ~(alignment - 1);
return reinterpret_cast<IndexerReversal*>(iThis)->m_parent;
}
public:
operator size_t() { struct SupportReverseIndexer* const parent = getParent(this); return parent->indexer(this-parent->ir.get()); }
};
SupportReverseIndexer() : ir(new IndexerReversal(this)) {}
operator IndexerReversal*() { return ir.get(); }
private:
std::auto_ptr<IndexerReversal> ir;
size_t indexer(size_t index) { printf("Custom operator[] called, index = %i\n", index); return index; }
};
const size_t SupportReverseIndexer::IndexerReversal::alignment = 0x10000 * sizeof(SupportReverseIndexer::IndexerReversal);
int main(void)
{
SupportReverseIndexer sri;
int a = sri[2];
a = 3[sri];
a = (-5)[sri];
return 0;
}
No, really, DON'T DO THIS!!!!!
It is completely impossible to do. Potatoswatter correctly points out you couldn't possibly define any operator such as operator[](int, T), so overloading for an integer on the left is impossible.
But consider that this works:
struct foo
{
operator const foo*() const
{
return this;
}
};
int main()
{
foo f;
5[f]; // UB
}
Is there a way to utilize this? No:
5.2.1 Subscripting
A postfix expression followed by an expression in square brackets is a postfix expression. One of the expressions shall have the type “pointer to T” and the other shall have enumeration or integral type. The result is an lvalue of type “T.” The type “T” shall be a completely-defined object type.56) The expression E1[E2] is identical (by definition) to *((E1)+(E2)).
With E1 being an integral type, E2 must be a pointer type. So we can't inject user-behavior there.
The only thing left is + and *. We can't change operator+ for an integral type and a pointer, because that's defined by the language. The result of E1 + E2 is going to be a pointer, and we can't define operator* for a pointer either.
Therefore, injecting user-defined behavior is impossible.
a[i] = 10;
i[a] = 10;
because a[i] is a postfix expression that is *(a+i) or *(i+a) because commutative property of addition.
Yes. But a[i] == i[a] == *(a+i) == *(i+a) is because the notation a[i] in C is a syntactic sugar for the latter pointer arithmetic. Keyword here "in C". C++ in large tries to part ways from the pointer arithmetic. Thus the a[i] as a syntactic sugar is only supported on the POD for backward compatibility with the C. But that does not work on any C++ objects since the operations [] has clear semantic specified and it doesn't allow the C-like syntax tricks.
In the end, do not do it. The trick is an obscure remnant of the older times and doesn't have a single good reason to be reincarnated.
Any Dummy that was declared and used as an array will work the same way, if Dummy can be implicitly cast to an integer.
You will need to define the Dummy::operator[](const Dummy& ref) to exhibit the desired property. For instance:
#include <iostream>
class dummy
{
public:
int operator[](const dummy& ref) { return 0; }
};
int main(int argc, char *argv[])
{
dummy d1, d2;
std::cout << (d1[d2] == d2[d1] ? "Yes" : "No");
}
Of course this is probably not exactly what you're looking for, but the tricky bit will be to replace the return 0; and possibly the return type with something that you have to define and that satisfies your intent.
Why exactly would you want this? Is it just a mental exercise?