c++ about operator* overloading - c++

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;
}

Related

c++ copy assignment operator for reference object variable

I give the following example to illustrate my question:
class Abc
{
public:
int a;
int b;
int c;
};
class Def
{
public:
const Abc& abc_;
Def(const Abc& abc):abc_(abc) { }
Def& operator = (const Def& obj)
{
// this->abc_(obj.abc_);
// this->abc_ = obj.abc_;
}
};
Here I do not know how to define the copy assignment operator. Do you have any ideas? Thanks.
references cannot be assigned to. You need something that can. A pointer would work, but they're very abusable.
How about std::reference_wrapper?
#include <functional>
class Abc
{
public:
int a;
int b;
int c;
};
class Def
{
public:
std::reference_wrapper<const Abc> abc_;
Def(const Abc& abc):abc_(abc) { }
// rule of zero now supplies copy/moves for us
// use the reference
Abc const& get_abc() const {
return abc_.get();
}
};
A reference cannot be assigned. Due to this, one can only define it via placement new and copy construction:
Def& operator = (const Def& obj)
{
this->~Def(); // destroy
new (this) Def(obj); // copy construct in place
}
But it is really unnecesary. Just use a pointer.

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.

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.

Trigger cast operator on use of the dot operator

I have a class something like this:
template<typename T>
class wrapper
{
public:
operator const T & () const
{
return value;
}
private:
T value;
};
I then use it with a struct like this:
struct point { float x; float y; };
//...
wrapper<point> myPoint;
std::cout << myPoint.x;// error: no member x or whatever.
I'm wondering if there's a way to allow this without having to do ((point)myPoint).x. I know that I can overload the -> operator but I'd prefer not to since its supposed to "pretend" to be a non-pointer.
You can achieve something similar with -> instead of .:
template<typename T>
class wrapper
{
public:
operator const T & () const // will this still be needed now?
{
return value;
}
T* operator->() { return &value; }
T const* operator->() const { return &value; }
private:
T value;
};
And then:
struct point { float x; float y; }
//...
wrapper<point> myPoint; // this needs to be initialised!
std::cout << myPoint->x;
You cannot make your wrapper class pretend to be a real class the way you described. The main reason is that member selection (.) operator cannot be overloaded.

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->()