Create pointer to "this" object - c++

I seem to be having issues in a project trying to create a pointer to "this" where "this" is the first LinkedList in a list in C++. The first object has data in it, second does...etc until the this->m_next is NULL
The compiler is spitting this out at me:
linkedlist.hpp:55:22: error: invalid conversion from âconst LinkedList<int>* constâ to âLinkedList<int>*â [-fpermissive]
What am I doing wrong?
template <typename T>
int LinkedList<T>::size() const
{
int count = 0;
LinkedList* list = this; // this line is what the compiler is complaining about
//adds to the counter if there is another object in list
while(list->m_next != NULL)
{
count++;
list = list->m_next;
}
return count;
}

The member function is marked const. Which means that this is const as well. You need to do:
const LinkedList<T>* list = this; // since "this" is const, list should be too
// ^
// |
// Also added the template parameter, which you need, since "this"
// is a LinkedList<T>

Change
LinkedList* list = this;
to
const LinkedList<T>* list = this;
^^^^^ ^^^
Since your function is defined as const, the this pointer is automatically of type const LinkedList<T>*
Thus you cannot assign a const pointer to a non const pointer, explaining the error.
The missing <T> would likely give you errors if you try non int parameters.

Try changing
LinkedList* list = this; // this line is what the compiler is complaining about
to
LinkedList<T> const * list = this;
^^^ ^^^^^

Related

operator == overload for double linked list

I have realized Double Linked List. And now i need to overload == operator.
dll.cpp:67:17: error: expected expression
if ([ind] != sp[ind]) {
The problem i don't understand how to overload == operator if only one parameter is given. I mean if i write bool operator ==(DLL sp1, DLL sp2){} compiler says error: overloaded 'operator==' must be a binary operator (has 3 parameters)
#include<iostream>
#include<string>
using namespace std;
template<typename T>
class DLL {
public:
DLL(){
size = 0;
head = nullptr;
tail = nullptr;
}
T operator [](int ind) {
int counter = 0;
T res = T();
Node *cur = this->head;
while(cur != nullptr) {
if(counter == ind) {
res = cur->data;
}
cur = cur->next;
counter++;
}
return res;
}
bool operator ==(DLL<int> sp){
bool isequal = true;
for(int ind = 0; ind < sp.length(); ind++){
if ([ind] != sp[ind]) {
isequal = false;
}
}
return isequal;
}
void clear() {
while(size != 1)
pop_front();
delete tail;
size--;
}
int length() {return size;}
}
private:
class Node{
public:
T data;
Node *next;
Node *prev;
Node(T data = T(), Node *prev= nullptr, Node *next = nullptr) {
this->data = data;
this->next = next;
this->prev = prev;
}
};
int size;
Node *head;
Node *tail;
};
The way you have it defined as a member function (and it only takes list of int for some reason (you should probably remove the <int>).
bool operator ==(DLL<int> sp); // There is a small issue in that you
// passing by value and thus causing a copy.
// Another issue with this is that it should
// probably marked "const" to indicate state
// is not changed by the call.
When the compiler see's this.
list1 == list2
This is simply syntactic sugar for:
list1.operator==(list2);
Thus is why you only need one parameter when you declare it as a member function. The alternative is to declare it as a friend function.
friend bool operator ==(DLL<T> const& lhs, DLL<T> const& rhs);
In this case it is a free standing function. When the compiler sees:
list1 == list2
This is syntactic sugar for:
operator==(list1, list2)
The problem was that you were defining a member function with two parameters. The left hand side is the class object and then you were expecting two objects on the right hand side (but the == operator only has one place on the right). That is why it is complaining about three parameters.
So the real question is should it be a member or a friend.
It does not matter here.
There are situations where it "can".
Example: If your class contains a single argument constructor (lets say you could create a list from an integer) and you use a member operator==()
DLL<int> list;
if (list == 5) {
}
This will now compile. Because your member operator uses a parameter and the compiler can convert an integer into the DLL parameter using a single argument constructor.
The counter argument to this is that normally you don't want automatic conversions of your type so you should mark single argument constructors as explicit to prevent this.
So:
If you class can automatically be created via a one argument constructor (most cases this is not true but it can be).
Then you should prefer a friend function version.
otherwise it does not matter and I would probably fall towards the member function.
You're doing the right thing for the most part.
The problem that is causing this error:
dll.cpp:67:17: error: expected expression if ([ind] != sp[ind]) {
is that you actually want to do this instead:
*this[ind] != sp[ind]
Also, there appears to be an extra } right here:
int length() {return size;}
} // <- not exactly sure what that's about, but I don't think you need it.
A comparison operator is a binary operator that treats both the operands equally, it is advisable to make it a friend function and not a member.
So the declaration for the function would change to
friend bool operator ==(const DLL<int> & lhs, const DLL<int> & rhs);
You can choose to define it inside or outside the class.
Read here on when you need to make an operator member vs non-member.

c++ - call member function on dereferenced object pointer

template <typename T>
class Node {
private:
T data;
Node<T> * next;
public:
Node(T _data, Node<T> * _next): data(_data), next(_next){}
T get_data() const {
return this->data;
}
Node<T> * get_next() const {
return this->next;
}
void set_data(T data) {
this->data = data;
}
void set_next(Node<T> * next) {
this->next = next;
}
};
now I try to invoke the 'set_next()' function on the dereferenced object pointer:
Node<T> new_element(element, NULL);
Node<T> * tmp = this->get_last(); // returns a pointer to the last element
*tmp.set_next(&new_element);
when I try to compile the console prints this errer message:
error: request for member ‘set_next’ in ‘tmp’, which is of pointer
type ‘Node<int>*’ (maybe you meant to use ‘->’ ?)
*tmp.set_next(&new_element);
I don't understand why the compiler wants me to use '->' because '.' is a perfectly fine way to invoke a public member function, right?
However when I put:
Node<T> new_element(element, NULL);
Node<T> * tmp = this->get_last();
*tmp->set_next(&new_element);
I get this:
error: void value not ignored as it ought to be
*tmp->set_next(&new_element);
I don't understand what that means, can someone help me?
Due to operator precedence,
*tmp.set_next(&new_element);
is the same as
*(tmp.set_next(&new_element));
which is clearly not what you want.
You may use
(*tmp).set_next(&new_element);
or
tmp->set_next(&new_element);
tmp->set_next(&new_element);
is the correct usage.
The error message occurs because the * tries to dereference the return value, which is void.

Returning node pointer using a template

Trying to search for a specific Node in a Tree, and I need to return a pointer to the Node when I've found it. The nodes are of a derived class type called BudgetEnvelope, and the error that I'm getting reads:
Cannot initialize return object of type BudgetEnvelope with an lvalue of type Node<BudgetEnvelope>
template <class T>
T* Tree<T>::find( Node<T> * ptr, T value){
if(ptr != NULL){
if(ptr->value == value){
return ptr; <------error is on this line
}
else{
if(value < ptr->value){
return find(ptr->left, value);
}
else{
return find(ptr->right, value);
}
}
}
else{
return NULL;
}
}
My understanding was that since the nodes are of the same type as the pointer that I am returning, that it should work. How can I resolve this?
Edit: More information.
When I change the return type to Node<T>*, the file where I am using this method gives me another error.
void EnvelopeBox::deposit(int id, double amount){
BudgetEnvelope searchKey = *new BudgetEnvelope(id, "searchKey");
BudgetEnvelope* keyPtr = envelopes.find(searchKey); <----same error
keyPtr->deposit(amount);
}
The deposit method is defined inside the BudgetEnvelope class, not Node, so if I change keyPtr to be the same type Node<T>*, I can't access the deposit method.
ptr is a pointer to type Node<T> and the function returns a pointer to type T. Types T and Node<T> are different.
If you want to return a T* you should return whatever method in your Node class returns a pointer to the value contained in that Node. Otherwise, which i think is what you want, change the signature of T* Tree<T>::find( Node<T> * ptr, T value) to return Node<T>*, as Justin suggested.
I think you want to return Node<T>* not T* because ptr is of type Node<T>*
e.g.
Node<T>* Tree<T>::find( Node<T> * ptr, T value)
EDIT:
With the new information you provided, what you need to do is convert
BudgetEnvelope* keyPtr = envelopes.find(searchKey);
to
Node<BudgetEnvelope>* keyPtr = envelopes.find(searchKey);
then to access the data inside, you do the following:
BudgetEnvelope myValue = keyPtr->Value;
myValue.deposit(amount)
What you need to do is access the data inside the node.
Alternatively, you can return ptr->Value from your find function.

What is wrong in the function declaration?

Explain to me, please, in what a mistake in the declaration/description of this method?
class Set
{
struct Node {
// ...
};
// ...
Node* &_getLink(const Node *const&, int) const;
// ...
};
Node* &Set::_getLink(const Node *const &root, int t) const
{
// ...
}
I don't see mistakes, but the compiler (MS VS C++) gives out many syntax errors.
You forgot to fully qualify the name of Node (which is defined in the scope of Set):
Set::Node* &Set::_getLink(const Node *const &root, int t) const
// ^^^^^
Without the fully qualification, the compiler will look for a global type named Node, which does not exist.
The problem is a scoping one. You need to prefix Node here:
Set::Node* &Set::_getLink(const Node *const &root, int t) const
{
// ...
}
Indeed, Node is unknown at the time it is encountered (you are at namespace scope, not inside Set's scope). You can also use auto:
auto Set::_getLink(const Node *const &root, int t) const -> Node *&
{
// ...
}
After ->, you are at Set's scope and Node is known.
you dont define Node in global scope
so use this code
//by Set::Node we give compiler that this function exist in class Node
Set::Node* &Set::_getLink(const Node *const &root, int t) const
{
// ...
}

Changing address of a struct in C++ by ++ and -- operator

Is it possible to change the address of my current struct using the -- or ++ operator, i.e.:
mystruct* test = existing_mystruct;
test++ // instead of using: test = test->next_p;
I was trying to use this, but it seems to be const and gives me an Error: assignment to this (anachronism):
struct mystruct {
mystruct* next_p;
mystruct* prev_p;
void operatorplusplus () { this = next_p; }
void operatorminusminus() { this = prev_p; }
};
Objects have a constant address in memory while they exist.
You may copy them to a new address, however.
What you try to do is advance in a linked list. And it may be done with those operators if you overload them. But you will need to define that in a special handle class to wrap over the list nodes.
EDIT
The code for what I describe will look somewhat like this:
class mylist
{
struct mynode
{
//data
mynode* next;
mynode* prev;
} *curr;
public:
mylist& operator++() {curr = curr->next; return *this;}
};
Naturally you'd wanna do boundry checks and such, but that's the general idea.
No. this pointer is of type mystruct * const, which means its address is unchangeable.