Dereferencing class with overloaded * operator - c++

I'm trying to create a pointer to a class that have * operator overloaded, but it returns another value.
Class code:
template<class T> class Node
{
public:
T *pointer;
T& operator*()
{
return *pointer;
}
}
Then this code doesn't work, returning int instead of pointer:
Node<int>* examplePointer; //this works
Node<int> example; //creates an instance of Node<T> class
examplePointer = *example; //this doesn't work
How can I make pointers with overloaded * operator?

This Node<int>* example; means that example is a pointer on a Node<int> (yes, I am captain Obvious :) ).
If you use it afterward with *, that does mean that you're just dereferencing the pointer to accessto the Node<int>. So, basically you have something like:
*example; // Just a pointer dereference expression type
// is something like Node<int>
**example; // something like: example->operator*();
I do not really see what's your goal... Using a pointer to a container like this seems to creates a lot of indirection...
And more generally, you cannot overload an operator* outside a class definition, so you cannot define it for a pointer.

Try just Node<int> example. That gives you a Node, and *example will call your operator - so it behaves like a pointer.

Related

How to make a deep-const pointer

Let's say I want to represent a binary tree in C++. Usually, I want a Node struct like this:
struct Node {
Node* left
Node* right;
};
(Here I use struct and raw pointers just for simplicity. I know I should use smart pointers for memory management.)
This representation has a problem: I can never have a deep-const tree. (Correct me if I can.) I may mark a single Node const, but its children is hard-coded as non-const in the Node struct.
(I may use some template hack to make left and right optionally const, but this makes the const Node and non-const Node incompatible.)
Soon I found out, if I magically had some deep-const pointer (say deep_const_pointer, which makes constness transitive), I can use that pointer in Node so that having a const node automatically means having a const sub-tree.
I tried to write a deep-const pointer class, and here is what I end up with:
template <typename T>
class deep_const_pointer {
public:
explicit deep_const_pointer(const T* p_)
: p{const_cast<T*>(p_)} {}
const T& operator*() const { return *p; }
T& operator*() { return *p; }
const T* operator->() const { return p; }
T* operator->() { return p; }
// etc.
private:
T* p;
};
Here I cast out the const in the constructor and optionally add it back according to the constness of this pointer-like object. However, this implementation allows the following:
const int i = 42;
deep_const_pointer<int> p{&i};
*p = 0; // Oops!
So it depends on the user to correctly mark whether the pointer is const or not.
How should I build a deep-const pointer class? Ideally, I want the const check happen at compile-time, and that pointer class takes as much memory as a raw pointer. (Which rules out the solution to save the constness to a bool member variable and check on each access.)
EDIT: I checked std::experimental::propagate_const, and it is indeed not a "deep-const" pointer from my perspective. What I meant by deep-const pointer P is:
Constant P is pointer-to-const;
Mutable P is pointer-to-mutable;
A const reference to a non-const P is treated as if it were a const P;
Since pointer-to-const has value semantics, a const P should be trivially copyable.
propagate_const fails to match the requirement because:
It never accepts a pointer-to-const;
It is not copyable (copy constructors explicitly deleted);
From the comments and answer I received, I guess such a P is not implementable in C++.
Writing a transitive-const smart pointer is a solved problem, just look up std::experimental::propagate_const<>. It shouldn't be too hard to find appropriate implementations.
In your own try, you got constructing from a raw pointer wrong. You should not add const to the pointee-type, nor strip it out with a cast.
Fixed:
explicit deep_const_pointer(T* p_)
: p{p_} {}

C++ | Dereference a member pointer

Well, lets say that I have a struct or a class that has a lets say int pointer as one of its members, something like this:
struct /*or class*/ some_struct /*or class*/ {
int *pointer = NULL;
} *obj_pointer;
and as the program goes obj_pointer and obj_pointer->pointer get initialized, how can I dereference obj_pointer->pointer so that I can print(cout) for example the value of the memory the pointer is pointing to?
Just like any other pointer, using the dereference operator *:
std::cout << *obj_pointer->pointer;
The member access operator -> have higher operator precedence than the dereference operator *

How do I properly dereference an object to set it's member variable in the following case?

I'm implementing a tree by writing a class called Node, and I'm having issues concerning the following method and member variables:
class Node {
public:
// ...
void addChild(const std::shared_ptr<Node> node);
private:
// ...
std::vector< std::shared_ptr<Node> > _children;
std::shared_ptr<Node> _parent;
};
When addChild is called by a Node object, it's simply supposed to set the argument's _parent member to point to the caller, then add the argument to the caller's vector of children. My implementation currently looks like this:
void Node::addChild(const std::shared_ptr<Node> node) {
if (!node) {
std::invalid_argument("Argument node must be nonnull.");
}
*node._parent = this;
_children.push_back(node);
}
The troublesome line is *node._parent = this;, which causes this error:
src/Node.cpp:89:10: error: no member named '_parent' in
'std::__1::shared_ptr<Node>'; did you mean to use '->' instead of '.'?
My train of thinking is telling me that I'm dereferencing node to gain access to the actual Node object, then using ._parent to gain access to the _parent member. Since _parent is a std::shared_ptr<Node>, it would then make sense to set it to equal this, which is a pointer to the calling object. But why is my compiler telling me that _parent doesn't exist when it definitely does exist?
Edit: I've also already attempted (*node)._parent, node->_parent, (*node)->_parent, and *(*node)._parent, all to no avail. They all result in error: no viable overloaded '='.
Your line of code: *node._parent = this; has two issues:
operator precedence
assignment to shared_ptr
First operator precedence. Operator . is evaluated before operator *. So currently your code is similar to doing this:
*(node._parent)
node doesn't have a _parent member, but *node does. So, fix it by either:
(*node)._parent
Or even better:
node->_parent
Then, you have another issue that you can't just assign to shared_ptr with operator =() like this. You need to change
= this;
To:
.reset(this);
So in total,
node->_parent.reset(this);

What are the pointer-to-member operators ->* and .* in C++?

Yes, I've seen this question and this FAQ, but I still don't understand what ->* and .* mean in C++.
Those pages provide information about the operators (such as overloading), but don't seem to explain well what they are.
What are ->* and .* in C++, and when do you need to use them as compared to -> and .?
I hope this example will clear things for you
//we have a class
struct X
{
void f() {}
void g() {}
};
typedef void (X::*pointer)();
//ok, let's take a pointer and assign f to it.
pointer somePointer = &X::f;
//now I want to call somePointer. But for that, I need an object
X x;
//now I call the member function on x like this
(x.*somePointer)(); //will call x.f()
//now, suppose x is not an object but a pointer to object
X* px = new X;
//I want to call the memfun pointer on px. I use ->*
(px ->* somePointer)(); //will call px->f();
Now, you can't use x.somePointer(), or px->somePointer() because there is no such member in class X. For that the special member function pointer call syntax is used... just try a few examples yourself ,you'll get used to it
EDIT: By the way, it gets weird for virtual member functions pointers.
For member variables:
struct Foo {
int a;
int b;
};
int main ()
{
Foo foo;
int (Foo :: * ptr);
ptr = & Foo :: a;
foo .*ptr = 123; // foo.a = 123;
ptr = & Foo :: b;
foo .*ptr = 234; // foo.b = 234;
}
Member functions are almost the same.
struct Foo {
int a ();
int b ();
};
int main ()
{
Foo foo;
int (Foo :: * ptr) ();
ptr = & Foo :: a;
(foo .*ptr) (); // foo.a ();
ptr = & Foo :: b;
(foo .*ptr) (); // foo.b ();
}
In a nutshell: You use -> and . if you know what member you want to access. And you use ->* and .* if you don't know what member you want to access.
Example with a simple intrusive list
template<typename ItemType>
struct List {
List(ItemType *head, ItemType * ItemType::*nextMemPointer)
:m_head(head), m_nextMemPointer(nextMemPointer) { }
void addHead(ItemType *item) {
(item ->* m_nextMemPointer) = m_head;
m_head = item;
}
private:
ItemType *m_head;
// this stores the member pointer denoting the
// "next" pointer of an item
ItemType * ItemType::*m_nextMemPointer;
};
When you have a normal pointer (to an object or a basic type), you would use * to dereference it:
int a;
int* b = a;
*b = 5; // we use *b to dereference b, to access the thing it points to
Conceptually, we're doing the same thing with a member function pointer:
class SomeClass
{
public: void func() {}
};
// typedefs make function pointers much easier.
// this is a pointer to a member function of SomeClass, which takes no parameters and returns void
typedef void (SomeClass::*memfunc)();
memfunc myPointer = &SomeClass::func;
SomeClass foo;
// to call func(), we could do:
foo.func();
// to call func() using our pointer, we need to dereference the pointer:
foo.*myPointer();
// this is conceptually just: foo . *myPointer ();
// likewise with a pointer to the object itself:
SomeClass* p = new SomeClass;
// normal call func()
p->func();
// calling func() by dereferencing our pointer:
p->*myPointer();
// this is conceptually just: p -> *myPointer ();
I hope that helps explain the concept. We're effectively dereferencing our pointer to the member function. It's a little more complicated than that -- it's not an absolute pointer to a function in memory, but just an offset, which is applied to foo or p above. But conceptually, we're dereferencing it, much like we would dereference a normal object pointer.
So called "pointers" to members in C++ are more like offsets, internally. You need both such a member "pointer", and an object, to reference the member in the object. But member "pointers" are used with pointer syntax, hence the name.
There are two ways you can have an object at hand: you have a reference to the object, or you have a pointer to the object.
For the reference, use .* to combine it with a member pointer, and for the pointer, use ->* to combine it with a member pointer.
However, as a rule, don't use member pointers if you can avoid it.
They obey pretty counter-intuitive rules, and they make it possible to circumvent protected access without any explicit casting, that is, inadvertently…
Cheers & hth.,
You cannot dereference pointer to members as normal pointers — because member functions require this pointer, and you have to pass it somehow. So, you need to use these two operators, with object on one side, and pointer on another, e.g. (object.*ptr)().
Consider using function and bind (std:: or boost::, depending on whether you write C++03 or 0x) instead of those, though.
Pointer-to-member access operators: .* and ->*
The pointer-to-member access operators, .* and ->*, are for dereferencing a pointer to member in combination with an object and a pointer to object, respectively. This description applies to both pointers to data members and pointers to member functions.
For example, consider the class Foo:
struct Foo {
int i;
void f();
};
If you declare a member pointer, iPtr, to an int data member of Foo:
int Foo::* iPtr;
You can initialize this member pointer iPtr so that it points to the Foo::i member:
iPtr = &Foo::i;
To dereference this pointer, you need to use it in conjunction with a Foo object.
Consider now the object foo and the pointer to object fooPtr:
Foo foo;
Foo* fooPtr = &foo;
Then, you can dereference iPtr in combination with foo or fooPtr:
foo.*iPtr = 0;
fooPtr->*iPtr = 0;
Analogously, you can use .* and ->* with pointers to function members. Note however that you will need to enclose them between parentheses because the function call operator, i.e., (), has higher precedence than both .* and ->*:
void (Foo::*memFuncPtr)() = &Foo::f;
(foo.*memFuncPtr)();
(fooPtr->*memFuncPtr)();
To conclude: you need an object to dereference a pointer to a member, and which one you use, either .* or ->* for dereferencing the pointer to member, depends on whether this needed object is directly provided or through an object pointer.
C++17 — Using std::invoke() instead
The use of both operators can be replaced since C++17 by the std::invoke function template. std::invoke provides a unified way of dereferencing member pointers regardless of whether you use them in combination with an object or an object pointer, and also regardless of whether the pointer to member corresponds to a pointer to data member or pointer to member function:
// dereference a pointer to a data member
std::invoke(iPtr, foo) = 0; // with an object
std::invoke(iPtr, fooPtr) = 0; // with an object pointer
// dereference a pointer to a member function
std::invoke(memFuncPtr, foo); // with an object
std::invoke(memFuncPtr, fooPtr); // with an object pointer
This unified syntax corresponds to the ordinary function call syntax, and it may make it easier to write generic code.

overloaded "=" equality does not get called when making obj2 = obj1

i have this class called MemoryManager,
it is supposed to implement a simple smart pointer, (count reference);
i have a vector where i store the requested pointers,and i return the index of the pointer to the caller..
when a user creates a pointer of type MemoryManager he calls an initializer function called modified_malloc(size_t) , create a MemoryManager obj, alloc a memory space and store it into data,increase count, and store the object into global_MM_vecotr , and return the index as a pointer , when the use tries to use indirection ( ->) i return the appropriate real pointer from the vector, according to the index value..
class MemoryManager
{
public:
//operators overloading prototypes
private:
void* data;
int count ;
};
std::vector<MemoryManager*> global_MM_vecotr;
void* MemoryManager::operator=( void* x)
{
// some code here
}
the problem i am facing is that i overloaded a couple of operators, however when i try to run the code below the "=" operator doesn't get called..
can some1 point the problem out to me..
//the main code
{
MemoryManager* obj1 = (MemoryManager*) x->fun1(4); //fun1 returns an index to a MemoryManager obj in a vector;
MemoryManager* obj2 = obj1 ;
}
Edit: already tried the following , no change
{
MemoryManager*obj1 = (MemoryManager*) x->fun1(4); //fun1 returns an index to a Class obj in a vector;
MemoryManager*obj2 ;
*obj2 = *obj1;
}
{
MemoryManager* obj1 = ( MemoryManager*) x-> fun1(4);
MemoryManager* obj2;
obj2.operator =(*obj1);
}
From you code, you have defined operator= for the MemoryManager class taking a void* .
Your example code is initializing ClassA pointers and not assigning to MemoryManager instances.
There are three reasons why your code is not being called.
You are initializing not assigning, so if anything a constructor would be called rather than an assignment operator.
You are initializing pointers and not objects, pointers are basic types and you cannot provide overloaded operators for them.
You are using ClassA and not MemoryManager which you have actually provided the operator= for.
See spec, you cannot override pointer basic operations.
Might be a technicality, but you're not assigning a ClassA, you're assigning a ClassA* (ie, a pointer). I might be way off here, but this is where I'd lay the blame.
I suspect you're using the void pointer so that you can enter any kind of object. I'd recommend using a template instead combined with the boost::check library.