operator keyword and operator overloading simulation - c++

I understand that we can apply increment and decrement on intrinsic data types such as:
int a;
a++;
a--;
...etc.
However, in the following codes, if I omit the & in the line operator int& ( ) { return value; }, I will get a compile error. Please explain how and why using & makes the increment possible here:
#include <iostream>
class Foo {
public:
int value;
operator int& ( ) { return value; }
};
int main ( ) {
Foo p;
p.value = 10;
p++;
std::cout << p << std::endl;
std::cin.get ( );
return 0;
}

This function definition:
operator int&() { return value; }
Allows a conversion from your class Foo to a reference to int.
This line:
p++;
Cannot increment p as type Foo as the class does not have operator++ implemented. However it is able to convert p to a reference to int via a call to operator int&() which returns a reference to value within the particular instance of Foo. The reference to value is of type int which can be incremented using ++. So the code then increments value in-place.
As to the distinction between returning an in and a reference to int, the following code shows the behaviour you mention is not distinct to the conversion oeprator:
class Foo
{
public:
Foo() : m_value(0)
{
}
int getCopy() { return m_value; }
int& getRef() { return m_value; }
private:
int m_value;
};
int main()
{
Foo f;
// Works
f.getRef()++;
// Does not work on g++ with 'error: lvalue required as increment operand`
f.getCopy()++;
}
The reason you cannot do an increment when the conversion operator returns int rather than int& is that the increment operation requires an lvalue, i.e. something that can be the target of an assignment. See here for more detail.

Related

Using a wrapper class as a pointer to the type it wraps?

I have a simple wrapper class for Integer types, defined like so:
class Integer {
public:
Integer() {
}
Integer(const int& value) {
this->value = value;
}
int toInt() const {
return value;
}
operator int() const {
return toInt();
}
private:
int value = 0;
};
What I'd like to do, is pass the class above to a function which has a signature like this:
doSomething(int* value)
If I were to use a normal int, I could simply do:
int value = 5;
doSomething(&value);
However, when using the wrapper class I can't since it would use a pointer to the class instead of the actual underlying value.
I know of the address operator operator&, which I could use to return a pointer to the value, but it would prevent me from getting a pointer to the class itself if I needed to.
So ideally there would be a way that would allow me to use &myclass to get a pointer to the class or the underlying value, depending on what is needed.
Is there such a way?
It seems I was able to solve my own problem.
I took some inspiration from a comment by #Arunmu and the following question: https://stackoverflow.com/a/9569120
By overloading the operator&() (address-of) operator and returning a proxy class object, which has implicit conversion operators to pointers of both the type of my original class and the value it wraps I can use the syntax I needed.
I will provide an example for anyone who encounters the same problem:
class IntegerPointer {
public:
IntegerPointer(int& value, Integer& wrapper) : value(value), wrapper(wrapper) {
}
operator int*() {
return &value;
}
operator Integer*() {
return std::addressof(wrapper);
}
private:
int& value;
Integer& wrapper;
};
class Integer {
public:
Integer() {
}
Integer(const int& value) : value(value) {
}
Integer(const Integer& value) : Integer(value.value) {
}
IntegerPointer operator&() {
return IntegerPointer(value, (*this));
}
protected:
int value;
};
This allows you to use syntax such as:
Integer test = 5;
doSomething(&test);
Where &test can be used as a pointer to the Integer object or as a pointer to the int value it wraps.

C++ increment ++ operator overloading

i know how to overload operator += if i am using a class for e.g.
class temp
{
public:
int i;
temp(){ i = 10; }
int operator+=(int k)
{
return i+=k;
}
};
int main()
{
temp var;
var += 67;
cout << var.i;
return 0;
}
But why cant i create a overloaded += function for basic datatype
int operator+=(int v, int h)
{
return v += (2*h);
}
int main()
{
int var = 10;
var += 67;
cout << i;
return 0;
}
i am getting error when i am compiling the above overloaded function.
It's not allowed to overload operators for primitive types. For reference see it written here:
http://www.cprogramming.com/tutorial/operator_overloading.html
Yet, you can have a similar effect by creating a "wrapper" class around the primitive type you want to overload and then creating a "conversion constructor" to go from the primitive type to your custom class and another "conversion operator" to go from your wrapper custom type back to the primitive type.
For you temp class something like this:
class temp
{
public:
int i;
temp(const int& orig){ i = orig; }
operator int(void) const { return i; }
int operator+=(int k)
{
return i+=k;
}
};
Operator overloading is not supported for primitive types. These operations are performed by direct CPU instructions. This is probably for a good reason though, as code that overloads basic arithmetic functions would be impossible to maintain.

c++ about operator* overloading

Is there any possible way to overload operator* in such way that it's assigning and observing functions are defined apart?
class my_class
{
private:
int value;
public:
int& operator*(){return value;}
};
int main()
{
my_class obj;
int val = 56;
*obj = val; // assign
val = *obj; // observe, same operator* is called
}
Sort of -- you can have the operator* return an instance of another class, rather than returning a reference directly. The instance of the other class then defines both a conversion operator and an assignment operator.
(In your sample code, it looks like you've overloaded the multiplication operator when you meant to overload the dereferencing operator; I'll use the dereferencing operator below.)
For example:
class my_class
{
friend class my_class_ref;
public:
my_class_ref operator*() { return my_class_ref(this); }
private:
int value;
};
class my_class_ref
{
public:
operator int() { return owner->value; } // "observe"
my_class_ref& operator=(int new_value) { owner->value = new_value; return *this; } // "assign"
private:
my_class* owner;
my_class_ref(my_class* owner) { this->owner = owner; }
};
There are some caveats. For example, as my_class_ref is implemented with a pointer to its parent class, your code must be careful that my_class_ref always has a lifetime shorter than the lifetime of the corresponding my_class -- otherwise you will dereference an invalid pointer.
In practice, if you pretend that my_class_ref doesn't exist (i.e. never declare a variable with that class) it can work very well.
Write your class like so
class my_class
{
private:
int value;
public:
int operator*() const { // observing
return value;
}
int& operator*() { // assigning
return value;
}
};
Then these operators are dissambiguated by constness, so code like this is possible
int _tmain(int argc, _TCHAR* argv[])
{
my_class a;
*a = 1; // assigning
int k = *(const_cast<my_class const&>(a)); // observing
return 0;
}

Overloaded 'dereference' or 'member of pointer' operators don't get run when I have a pointer to an object

I have the following code:
#include <iostream>
struct Base {
int i_;
};
class El : protected Base {
public:
int get_i() const { return i_; }
void set_i(int i) { i_ = i; }
};
class It : protected Base {
public:
using pointer = const El*;
using reference = const El&;
reference operator*() const
{
return reinterpret_cast<reference>(*this);
}
pointer operator->() const
{
return reinterpret_cast<pointer>(this);
}
};
int main()
{
It it;
It* itp = &it;
std::cout << *****(itp)->get_i() << "\n"; //ERROR
}
Both GCC and Clang++ somehow fail to invoke either of operator* or operator->, so I get an error It doesn't have member function 'get_i' in the last line regardless how many indirections I try. Does the standard warrant such unintuitive behavior?
Operator precedence: -> binds more tightly, so is applied to the pointer itp.
When you overload operator->, that doesn't affect the meaning of operator-> applied to a pointer-to-your-class. You want (*itp)->get_i();, I think.

How do I create and use a class arrow operator? [duplicate]

This question already has answers here:
What are the basic rules and idioms for operator overloading?
(8 answers)
Closed 4 months ago.
So, after researching everywhere for it, I cannot seem to find how to create a class arrow operator, i.e.,
class Someclass
{
operator-> () /* ? */
{
}
};
I just need to know how to work with it and use it appropriately.
- what are its inputs?
- what does it return?
- how do I properly declare/prototype it?
The operator -> is used to overload member access. A small example:
#include <iostream>
struct A
{
void foo() {std::cout << "Hi" << std::endl;}
};
struct B
{
A a;
A* operator->() {
return &a;
}
};
int main() {
B b;
b->foo();
}
This outputs:
Hi
The arrow operator has no inputs. Technically, it can return whatever you want, but it should return something that either is a pointer or can become a pointer through chained -> operators.
The -> operator automatically dereferences its return value before calling its argument using the built-in pointer dereference, not operator*, so you could have the following class:
class PointerToString
{
string a;
public:
class PtPtS
{
public:
PtPtS(PointerToString &s) : r(s) {}
string* operator->()
{
std::cout << "indirect arrow\n";
return &*r;
}
private:
PointerToString & r;
};
PointerToString(const string &s) : a(s) {}
PtPtS operator->()
{
std::cout << "arrow dereference\n";
return *this;
}
string &operator*()
{
std::cout << "dereference\n";
return a;
}
};
Use it like:
PointerToString ptr(string("hello"));
string::size_type size = ptr->size();
which is converted by the compiler into:
string::size_type size = (*ptr.operator->().operator->()).size();
(with as many .operator->() as necessary to return a real pointer) and should output
arrow dereference
indirect dereference
dereference
Note, however, that you can do the following:
PointerToString::PtPtS ptr2 = ptr.operator->();
run online: https://wandbox.org/permlink/Is5kPamEMUCA9nvE
From Stroupstrup:
The transformation of the object p into the pointer p.operator->() does not depend on the member m pointed to. That is the sense in which operator->() is a unary postfix operator. However, there is no new syntax introduced, so a member name is still required after the ->
class T {
public:
const memberFunction() const;
};
// forward declaration
class DullSmartReference;
class DullSmartPointer {
private:
T *m_ptr;
public:
DullSmartPointer(T *rhs) : m_ptr(rhs) {};
DullSmartReference operator*() const {
return DullSmartReference(*m_ptr);
}
T *operator->() const {
return m_ptr;
}
};
http://en.wikibooks.org/wiki/C++_Programming/Operators/Operator_Overloading#Address_of.2C_Reference.2C_and_Pointer_operators
The "arrow" operator can be overloaded by:
a->b
will be translated to
return_type my_class::operator->()